[project @ 1997-03-24 04:33:27 by sof]
[ghc-hetmet.git] / ghc / driver / ghc.lprl
1 %
2 % (c) The GRASP/AQUA Project, Glasgow University, 1992-1997
3 %
4
5 This is the driver script for the Glasgow Haskell compilation system.
6 It is written in \tr{perl}.  The first section includes a long
7 ``usage'' message that describes how the driver is supposed to work.
8
9 %************************************************************************
10 %*                                                                      *
11 \section[Driver-usage]{Usage message}
12 %*                                                                      *
13 %************************************************************************
14
15 \begin{code}
16 ($Pgm = $0) =~ s|.*/||;
17 $ShortUsage  =  "\nUsage: For basic information, try the `-help' option.\n";
18 $LongUsage = "\n" . <<EOUSAGE;
19 Use of the Glorious Haskell Compilation System driver:
20
21     $Pgm [command-line-options-and-input-files]
22
23 ------------------------------------------------------------------------
24 This driver ($Pgm) guides each input file through (some of the)
25 possible phases of a compilation:
26
27     - unlit:    extract code from a "literate program"
28     - hscpp:    run code through the C pre-processor (if -cpp flag given)
29     - hsc:      run the Haskell compiler proper
30     - gcc:      run the C compiler (if compiling via C)
31     - as:       run the assembler
32     - ld:       run the linker
33
34 For each input file, the phase to START with is determined by the
35 file's suffix:
36     - .lhs      literate Haskell: unlit
37     - .hs       illiterate Haskell: hsc
38     - .hc       C from the Haskell compiler: gcc
39     - .c        C not from the Haskell compiler: gcc
40     - .s        assembly language: as
41     - other     passed directly to the linker: ld
42
43 If no files are given on the command line, input is taken from
44 standard input, and processing is as for an .hs file.  (All output is
45 to stdout or stderr, however).
46
47 The phase at which to STOP processing is determined by a command-line
48 option:
49     -C          stop after generating C (.hc output)
50     -E          stop after generating preprocessed C (.i output)
51     -S          stop after generating assembler (.s output)
52     -c          stop after generating object files (.o output)
53
54 Other commonly-used options are:
55
56     -O          An `optimising' package of compiler flags, for faster code
57
58     -prof       Compile for cost-centre profiling
59                 (add -auto for automagic cost-centres on top-level functions)
60
61     -fglasgow-exts  Allow Glasgow extensions (unboxed types, etc.)
62
63     -H14m       Increase compiler's heap size
64
65     -M          Output the Makefile rules recording the
66                 dependencies of a list of Haskell files.
67                 (ghc driver just calls upon the help of a
68                  compatible mkdependHS script to do the
69                  actual processing)
70
71 The User's Guide has more information about GHC's *many* options.
72
73 Given the above, here are some TYPICAL invocations of $Pgm:
74
75     # compile a Haskell module to a .o file, optimising:
76     % $Pgm -c -O Foo.hs
77     # link three .o files into an executable called "test":
78     % $Pgm -o test Foo.o Bar.o Baz.o
79     # compile a Haskell module to C (a .hc file), using a bigger heap:
80     % $Pgm -C -H16m Foo.hs
81     # compile Haskell-produced C (.hc) to assembly language:
82     % $Pgm -S Foo.hc
83 ------------------------------------------------------------------------
84 EOUSAGE
85 \end{code}
86
87 %************************************************************************
88 %*                                                                      *
89 \section[Driver-init]{Initialisation}
90 %*                                                                      *
91 %************************************************************************
92
93 The driver script need to be told where to find these executables, so
94 in the course of building the driver `executable', make-variables holding
95 these are prepended to the de-litted version of this file. The variables are:
96
97 \begin{verbatim}
98 INSTALLING
99
100 HOSTPLATFORM TARGETPLATFORM
101
102 PROJECTNAME PROJECTVERSION PROJECTPATCHLEVEL
103
104 TOP_PWD
105
106 bindir libdir datadir
107
108 CURRENT_DIR TMPDIR
109
110 GHC_LIB_DIR GHC_RUNTIME_DIR GHC_UTILS_DIR GHC_INCLUDE_DIR
111
112 GHC_OPT_HILEV_ASM GhcWithNativeCodeGen
113
114 GHC_UNLIT GHC_HSCPP GHC_HSC GHC_SYSMAN
115
116 CP RM CONTEXT_DIFF
117
118 WAY_*_NAME WAY_*_HC_OPTS
119
120 LeadingUnderscore
121
122 \end{verbatim}
123
124 Establish what executables to run for the various phases, what the
125 default options are for those phases, and other similar boring stuff.
126
127 \begin{code}
128 select(STDERR); $| = 1; select(STDOUT); # no STDERR buffering, please.
129
130 $TargetPlatform = $TARGETPLATFORM;
131
132 $TopPwd         = "${TOP_PWD}";
133 $InstBinDirGhc  = "${bindir}";
134 $InstLibDirGhc  = "${libdir}";
135 $InstDataDirGhc = "${datadir}";
136 $InstSysLibDir  = ( $INSTALLING ) ? "${InstLibDirGhc}/hslibs" : "$TopPwd/hslibs";
137
138 $Status  = 0; # just used for exit() status
139 $Verbose = '';
140
141 # set up signal handler
142 sub quit_upon_signal { &tidy_up_and_die(1, ''); }
143 $SIG{'INT'}  = 'quit_upon_signal';
144 $SIG{'QUIT'} = 'quit_upon_signal';
145
146 # where to get "require"d .prl files at runtime (poor man's dynamic loading)
147 #   (use LIB, not DATA, because we can't be sure of arch-independence)
148 @INC = ( ( $INSTALLING ) ? $InstLibDirGhc
149                            : "$TopPwd/${CURRENT_DIR}" );
150
151 if ( $ENV{'TMPDIR'} ) { # where to make tmp file names
152     $Tmp_prefix = ($ENV{'TMPDIR'} . "/ghc$$");
153 } else {
154     print STDERR "TMPDIR has not been set to anything useful!\n" if (${TMPDIR} eq '');
155     $Tmp_prefix ="${TMPDIR}/ghc$$"; # TMPDIR set via Makefile when booting..
156     $ENV{'TMPDIR'} = ${TMPDIR}; # set the env var as well
157 }
158
159 @Files_to_tidy = (); # files we nuke in the case of abnormal termination
160
161 $Unlit = ( $INSTALLING ) ? "$InstLibDirGhc/unlit"
162                          : "$TopPwd/${CURRENT_DIR}/${GHC_UNLIT}";
163
164 $Cp   = $CP;
165 $Rm   = $RM;
166 $Diff = $CONTEXT_DIFF;
167 $Cat  = 'cat';
168 $Cmp  = 'cmp';
169 $Time = '';
170
171 $HsCpp   = # but this is re-set to "cat" (after options) if -cpp not seen
172            ( $INSTALLING ) ? "$InstLibDirGhc/hscpp"
173                            : "$TopPwd/${CURRENT_DIR}/${GHC_HSCPP}";
174
175 @HsCpp_flags    = ();
176 $genSPECS_flag  = '';           # See ../utils/hscpp/hscpp.prl
177 $HsC     = ( $INSTALLING ) ? "$InstLibDirGhc/hsc"
178                            : "$TopPwd/${CURRENT_DIR}/${GHC_HSC}";
179
180 # For PVM fiends only
181 $SysMan  = ( $INSTALLING ) ? "$InstLibDirGhc/SysMan"
182                            : "$TopPwd/${CURRENT_DIR}/${GHC_SYSMAN}";
183
184 @Unlit_flags    = ();
185
186 #
187 # HsC_rts_flags: if we want to talk to the LML runtime system
188 # NB: we don't use powers-of-2 sizes, because this may do
189 #   terrible things to cache behavior.
190 #
191 $Specific_heap_size = 6 * 1000 * 1000;
192 $Specific_stk_size  = 1000 * 1000;
193 $Scale_sizes_by     = 1.0;
194
195 \end{code}
196
197 The variables set by @setupOptFlags@ represent parts of the
198 -O/-O2/etc ``templates,'' which are filled in later, using these.
199 These are the default values, which may be changed by user flags.
200
201 \begin{code}
202 sub setupOptFlags {
203    $Oopt_UnfoldingUseThreshold    = '-fsimpl-uf-use-threshold3';
204    $Oopt_MaxSimplifierIterations  = '-fmax-simplifier-iterations4';
205    $Oopt_PedanticBottoms          = '-fpedantic-bottoms'; # ON by default
206    $Oopt_MonadEtaExpansion        = '';
207    $Oopt_FinalStgProfilingMassage = '';
208    $Oopt_StgStats                 = '';
209    $Oopt_SpecialiseUnboxed        = '';
210    $Oopt_DoSpecialise             = ''; # ToDo:LATER: '-fspecialise';
211    $Oopt_FoldrBuild               = 0; # *Off* by default!
212    $Oopt_FB_Support               = ''; # was '-fdo-arity-expand';
213 #  $Oopt_FoldrBuildWW             = 0; # Off by default
214    $Oopt_FoldrBuildInline         = ''; # was '-fdo-inline-foldr-build';
215 } # end of setupOptFlags
216
217 # Assign defaults to these right away.
218 &setupOptFlags();
219 \end{code}
220
221 Things to do with C compilers/etc:
222 \begin{code}
223 $CcRegd         = $GHC_OPT_HILEV_ASM;
224 @CcBoth_flags   = ('-S');   # flags for *any* C compilation
225 @CcInjects      = ();
226
227 # GCC flags: 
228 #    those for all files, 
229 #    those only for .c files;
230 #    those only for .hc files
231
232 @CcRegd_flags    = ('-ansi', '-D__STG_GCC_REGS__', '-D__STG_TAILJUMPS__');
233 @CcRegd_flags_c = ();
234 @CcRegd_flags_hc = ();
235
236 $As             = ''; # "assembler" is normally GCC
237 @As_flags       = ();
238
239 $Lnkr           = ''; # "linker" is normally GCC
240 @Ld_flags       = ();
241
242 # 'nm' is used for consistency checking (ToDo: mk-world-ify)
243 # ToDo: check the OS or something ("alpha" is surely not the crucial question)
244 $Nm = ($TargetPlatform =~ /^alpha-/) ? 'nm -B' : 'nm';
245 \end{code}
246
247 What options \tr{-user-setup-a} turn into (user-defined ``packages''
248 of options).  Note that a particular user-setup implies a particular
249 Prelude ({\em including} its interface file(s)).
250 \begin{code}
251 $BuildTag       = ''; # default is sequential build w/ Appel-style GC
252
253 %BuildDescr     = (# system ways begin
254                    '',      'normal sequential',
255                    '_p',    "$WAY_p_NAME",
256                    '_t',    "$WAY_t_NAME",
257                    '_u',    "$WAY_u_NAME",
258                    '_mc',   "$WAY_mc_NAME",
259                    '_mr',   "$WAY_mr_NAME",
260                    '_mt',   "$WAY_mt_NAME",
261                    '_mp',   "$WAY_mp_NAME",
262                    '_mg',   "$WAY_mg_NAME",
263                    '_2s',   "$WAY_2s_NAME",
264                    '_1s',   "$WAY_1s_NAME",
265                    '_du',   "$WAY_du_NAME",
266                    # system ways end
267                    '_a',    "$WAY_a_NAME",
268                    '_b',    "$WAY_b_NAME",
269                    '_c',    "$WAY_c_NAME",
270                    '_d',    "$WAY_d_NAME",
271                    '_e',    "$WAY_e_NAME",
272                    '_f',    "$WAY_f_NAME",
273                    '_g',    "$WAY_g_NAME",
274                    '_h',    "$WAY_h_NAME",
275                    '_i',    "$WAY_i_NAME",
276                    '_j',    "$WAY_j_NAME",
277                    '_k',    "$WAY_k_NAME",
278                    '_l',    "$WAY_l_NAME",
279                    '_m',    "$WAY_m_NAME",
280                    '_n',    "$WAY_n_NAME",
281                    '_o',    "$WAY_o_NAME",
282                    '_A',    "$WAY_A_NAME",
283                    '_B',    "$WAY_B_NAME" );
284
285 # these are options that are "fed back" through the option processing loop
286 #
287 %SetupOpts = 
288        (
289         '_a', "$WAY_a_HC_OPTS",
290         '_b', "$WAY_b_HC_OPTS",
291         '_c', "$WAY_c_HC_OPTS",
292         '_d', "$WAY_d_HC_OPTS",
293         '_e', "$WAY_e_HC_OPTS",
294         '_f', "$WAY_f_HC_OPTS",
295         '_g', "$WAY_g_HC_OPTS",
296         '_h', "$WAY_h_HC_OPTS",
297         '_i', "$WAY_i_HC_OPTS",
298         '_j', "$WAY_j_HC_OPTS",
299         '_k', "$WAY_k_HC_OPTS",
300         '_l', "$WAY_l_HC_OPTS",
301         '_m', "$WAY_m_HC_OPTS",
302         '_n', "$WAY_n_HC_OPTS",
303         '_o', "$WAY_o_HC_OPTS",
304         '_A', "$WAY_A_HC_OPTS",
305         '_B', "$WAY_B_HC_OPTS",
306
307         # system ways
308         '_p',  "$WAY_p_HC_OPTS",
309         '_t',  "$WAY_t_HC_OPTS",
310         '_u',  "$WAY_u_HC_OPTS",
311         '_mc', "$WAY_mc_HC_OPTS",
312         '_mr', "$WAY_mr_HC_OPTS",
313         '_mt', "$WAY_mt_HC_OPTS",
314         '_mp', "$WAY_mp_HC_OPTS",
315         '_mg', "$WAY_mg_HC_OPTS",
316         '_2s', "$WAY_2s_HC_OPTS",
317         '_1s', "$WAY_1s_HC_OPTS",
318         '_du', "$WAY_B_HC_OPTS" );
319
320 # per-build code fragments which are eval'd
321 #%EvaldSetupOpts        = ('',      '', # this one must *not* be set!
322
323 #                           # profiled sequential
324 #                  '_p',    'push(@HsC_flags,  \'-fscc-profiling\');
325 #                            push(@CcBoth_flags, \'-DPROFILING\');',
326
327 #                           #and maybe ...
328 #                           #push(@CcBoth_flags, '-DPROFILING_DETAIL_COUNTS');
329
330 #                           # ticky-ticky sequential
331 #                  '_t',    'push(@HsC_flags, \'-fticky-ticky\');
332 #                            push(@CcBoth_flags, \'-DTICKY_TICKY\');',
333
334 ##OLD:                      # unregisterized (ToDo????)
335 ##                 '_u',    '',
336
337 #                           # concurrent
338 #                  '_mc',   '$StkChkByPageFaultOK = 0;
339 #                            push(@HsC_flags,  \'-fconcurrent\');
340 #                            push(@HsCpp_flags,\'-D__CONCURRENT_HASKELL__\', \'-DCONCURRENT\');
341 #                            push(@Cpp_define, \'-D__CONCURRENT_HASKELL__\', \'-DCONCURRENT\');',
342
343 #                           # profiled concurrent
344 #                  '_mr',   '$StkChkByPageFaultOK = 0;
345 #                            push(@HsC_flags,  \'-fconcurrent\', \'-fscc-profiling\');
346 #                            push(@HsCpp_flags,\'-D__CONCURRENT_HASKELL__\', \'-DCONCURRENT\');
347 #                            push(@Cpp_define, \'-D__CONCURRENT_HASKELL__\', \'-DCONCURRENT\', \'-DPROFILING\');',
348
349 #                           # ticky-ticky concurrent
350 #                  '_mt',   '$StkChkByPageFaultOK = 0;
351 #                            push(@HsC_flags,  \'-fconcurrent\', \'-fticky-ticky\');
352 #                            push(@HsCpp_flags,\'-D__CONCURRENT_HASKELL__\', \'-DCONCURRENT\');
353 #                            push(@Cpp_define, \'-D__CONCURRENT_HASKELL__\', \'-DCONCURRENT\', \'-DTICKY_TICKY\');',
354
355 #                           # parallel
356 #                  '_mp',   '$StkChkByPageFaultOK = 0;
357 #                            push(@HsC_flags,  \'-fconcurrent\');
358 #                            push(@HsCpp_flags,\'-D__PARALLEL_HASKELL__\',   \'-DPAR\');
359 #                            push(@Cpp_define, \'-D__CONCURRENT_HASKELL__\', \'-DCONCURRENT\', \'-DPAR\');',
360
361 #                           # GranSim
362 #                  '_mg',   '$StkChkByPageFaultOK = 0;
363 #                            push(@HsC_flags,  \'-fconcurrent\', \'-fgransim\');
364 #                            push(@HsCpp_flags,\'-D__GRANSIM__\',   \'-DGRAN\');
365 #                            push(@Cpp_define, \'-D__CONCURRENT_HASKELL__\', \'-DCONCURRENT\', \'-DGRAN\');',
366
367 #                  '_2s',   'push (@CcBoth_flags, \'-DGC2s\');',
368 #                  '_1s',   'push (@CcBoth_flags, \'-DGC1s\');',
369 #                  '_du',   'push (@CcBoth_flags, \'-DGCdu\');',
370
371 #                  '_a',    '', # these user-way guys should not be set!
372 #                  '_b',    '',
373 #                  '_c',    '',
374 #                  '_d',    '',
375 #                  '_e',    '',
376 #                  '_f',    '',
377 #                  '_g',    '',
378 #                  '_h',    '',
379 #                  '_i',    '',
380 #                  '_j',    '',
381 #                  '_k',    '',
382 #                  '_l',    '',
383 #                  '_m',    '',
384 #                  '_n',    '',
385 #                  '_o',    '',
386 #                  '_A',    '',
387 #                  '_B',    '' );
388
389 \end{code}
390
391 Import/include directories (\tr{-I} options) are sufficiently weird to
392 require special handling.
393
394 \begin{code}
395 @Import_dir     = ('.'); #-i things
396 @Include_dir    = ('.'); #-I things; other default(s) stuck on AFTER option processing
397
398 # where to look for interface files (system hi's, i.e., prelude and hslibs)
399 @SysImport_dir  = ( $INSTALLING )
400                     ? ( "$InstLibDirGhc/imports" )
401                     : ( "$TopPwd/$CURRENT_DIR/$GHC_LIB_DIR/required"
402                       , "$TopPwd/$CURRENT_DIR/$GHC_LIB_DIR/ghc"
403                       , "$TopPwd/$CURRENT_DIR/$GHC_LIB_DIR/glaExts"
404                       , "$TopPwd/$CURRENT_DIR/$GHC_LIB_DIR/concurrent" );
405
406 # We need to look in ghc/ and glaExts/ when searching for implicitly needed .hi files, but 
407 # we should really *not* look there for explicitly imported modules.
408
409 $GhcVersionInfo  = int ($PROJECTVERSION * 100);
410 $Haskell1Version = 4; # i.e., Haskell 1.4
411 @Cpp_define      = ();
412
413 @UserLibrary_dir= ();   #-L things;...
414 @UserLibrary    = ();   #-l things asked for by the user
415
416 @SysLibrary_dir = ( ( $INSTALLING )     #-syslib things supplied by the system
417                     ? $InstLibDirGhc
418                     : ( "$TopPwd/$CURRENT_DIR/$GHC_RUNTIME_DIR"
419                       , "$TopPwd/$CURRENT_DIR/$GHC_RUNTIME_DIR/gmp"
420                       , "$TopPwd/$CURRENT_DIR/$GHC_LIB_DIR"
421                       , "$TopPwd/$CURRENT_DIR/$GHC_LIB_DIR/cbits"
422                       )
423                   );
424 @SysLibrary = (); # will be built up as we go along
425
426 $TopClosureFile # defaults to 1.2 one; will be mangled later
427         = ( $INSTALLING)  ? "$InstLibDirGhc/TopClosureXXXX.o"
428                           : "$TopPwd/$CURRENT_DIR/$GHC_RUNTIME_DIR/main/TopClosureXXXX.o";
429
430 # make depend for Haskell
431 $MkDependHS
432         = ( $INSTALLING ) ? "$InstBinDirGhc/mkdependHS"
433                           : "$TopPwd/$CURRENT_DIR/$GHC_UTILS_DIR/mkdependHS/mkdependHS";
434 # Fill in later
435 @MkDependHS_flags = ( );
436
437 # do_link flag should not be reset while rescanning the cmd-line.
438 $Do_lnkr    = 1;
439 $Specific_output_dir = '';      # set by -odir <dir>
440 $Specific_output_file = '';     # set by -o <file>; "-" for stdout
441 \end{code}
442
443 Function to initialise the per-compilation-unit globals that
444 are used to guide and control the invocation of the different phases.
445
446 \begin{code} 
447 sub initDriverGlobals {
448
449 # reset the following options:
450 # RTS flags to use while compiling
451 @HsC_rts_flags      = ();
452 @HsP_flags      = (); # these are the flags destined solely for
453                       # the flex/yacc parser
454 @HsC_flags      = ();
455 @HsC_antiflags  = ();
456 \end{code}
457
458 The optimisations/etc to be done by the compiler are {\em normally}
459 expressed with a \tr{-O} (or \tr{-O2}) flag, or by its absence.
460
461 \begin{code}
462 $OptLevel      = 0; # no -O == 0; -O == 1; -O2 == 2; -Ofile == 3
463 $MinusO2ForC   = 0; # set to 1 if -O2 should be given to C compiler
464 $StolenX86Regs = 4; # **HACK*** of the very worst sort
465 $CoreLint      = '';
466 $StgLint       = '';
467
468 @CcBoth_flags   = ('-S');   # flags for *any* C compilation
469 @CcInjects      = ();
470
471 # GCC flags: those for all files, those only for .c files; those only for .hc files
472 @CcRegd_flags    = ('-ansi', '-D__STG_GCC_REGS__', '-D__STG_TAILJUMPS__');
473 @CcRegd_flags_c = ();
474 @CcRegd_flags_hc = ();
475
476 @Import_dir     = ('.'); #-i things
477 @Include_dir    = ('.'); #-I things; other default(s) stuck on AFTER option processing
478
479
480 \end{code}
481
482 We are given a list of files with various presumably-known suffixes
483 (unknown-suffix files go straight to the linker).  For each file, we
484 begin by assuming that we'll run every phase over it.  However: (1)
485 global flags (\tr{-c}, \tr{-S}, etc.) tell us not to run any phase
486 past a certain point; and (2) the file's suffix tells us what phase to
487 start with.  Linking is weird and kept track of separately.
488
489 Here are the initial defaults applied to all files:
490 \begin{code}
491 $Cpp_flag_set = 0;        # (hack)
492 $Only_preprocess_C = 0;   # pretty hackish
493 $Only_generate_deps = 0;  #
494 $PostprocessCcOutput = 0;
495
496 # native code-gen or via C?
497 $HaveNativeCodeGen = $GhcWithNativeCodeGen;
498 $HscOut = '-C='; # '-C=' ==> .hc output; '-S=' ==> .s output; '-N=' ==> neither
499 $HscOut = '-S='
500     if $HaveNativeCodeGen && $TargetPlatform =~ /^(alpha|sparc)-/;
501 # TEMP: disable x86  if $HaveNativeCodeGen && $TargetPlatform =~ /^(i386|alpha|sparc)-/;
502 $ProduceHi   = '-hifile=';
503 $HiOnStdout  = 0;
504 $HiDiff_flag = '';
505
506 $CollectingGCstats = 0;
507 $CollectGhcTimings = 0;
508 $DEBUGging = '';        # -DDEBUG and all that it entails (um... not really)
509 $PROFing = '';          # set to p or e if profiling
510 $PROFgroup = '';        # set to group if an explicit -Ggroup specified
511 $PROFauto = '';         # set to relevant hsc flag if -auto or -auto-all
512 $PROFcaf  = '';         # set to relevant hsc flag if -caf-all
513 $PROFignore_scc = '';   # set to relevant parser flag if explicit sccs ignored
514 $UNPROFscc_auto = '';   # set to relevant hsc flag if forcing auto sccs without profiling
515 $TICKYing = '';         # set to t if compiling for ticky-ticky profiling
516 $PARing = '';           # set to p if compiling for PAR
517 $CONCURing = '';        # set to c if compiling for CONCURRENT
518 $GRANing = '';          # set to g if compiling for GRAN
519 $StkChkByPageFaultOK = 1; # may be set to 0 (false) for some builds
520 $Specific_hi_file = '';         # set by -ohi <file>; "-" for stdout
521 $Specific_dump_file = '';       # set by -odump <file>; "-" for stdout
522 $Using_dump_file = 0;
523 $Isuffix    = '';
524 $Osuffix    = '';       # default: use the normal suffix for that kind of output
525 $HiSuffix   = 'hi';
526 $HiSuffix_prelude = '';
527 $Do_recomp_chkr = 0;    # don't use the recompilatio checker unless asked
528 $Do_cc      = -1;   # a MAGIC indeterminate value; will be set to 1 or 0.
529 $Do_as      = 1;
530
531 $Keep_hc_file_too = 0;
532 $Keep_s_file_too = 0;
533 $UseGhcInternals = 0; # if 1, may use GHC* modules
534 $SplitObjFiles = 0;
535 $NoOfSplitFiles = 0;
536 $Dump_parser_output = 0;
537 $Dump_raw_asm = 0;
538 $Dump_asm_splitting_info = 0;
539 $NoImplicitPrelude = 0;
540
541
542 } # end of initDriverGlobals (Sigh)
543
544 # we split the argv passed to the driver into three:
545
546 # the list of files
547 @Input_file = ();
548
549 # and files to be linked...
550 @Link_file  = ();
551
552 # and whatever else
553 @Cmd_opts  = ();
554
555 \end{code}
556
557 We inject consistency-checking information into \tr{.hc} files (both
558 when created by the Haskell compiler and when compiled by the C
559 compiler), so that we can check that an executable is made from
560 consistently-built pieces.  (The check is normally done just after
561 linking.)  The checking is done by introducing/munging
562 \tr{what(1)}-style strings.  Anyway, here are the relevant global
563 variables and their defaults:
564 \begin{code}
565 $LinkChk = 1;   # set to 0 if the link check should *not* be done
566
567 # major & minor version numbers; major numbers must always agree;
568 # minor disagreements yield a warning.
569 $HsC_major_version = 31;
570 $HsC_minor_version = 0;
571 $Cc_major_version  = 36;
572 $Cc_minor_version  = 0;
573
574 # options: these must always agree
575 $HsC_consist_options = '';    # we record, in this order:
576                               #     Build tag; debugging?
577 $Cc_consist_options  = '';    # we record, in this order:
578                               #     Build tag; debugging?
579 \end{code}
580
581 %************************************************************************
582 %*                                                                      *
583 \section[Driver-parse-argv]{Munge the command-line options}
584 %*                                                                      *
585 %************************************************************************
586
587 Now slurp through the arguments.
588 \begin{code}
589
590 #---------- user defined prelude ---------------------------------------
591
592 if (grep(/^-user-prelude$/, @ARGV)) {
593
594     # If ARGV contains -user-prelude we are compiling a piece of 
595     # prelude for the user, probably with additional specialise pragmas
596
597     # We strip out the -O -f and -user-prelude flags provided on
598     # the command line and add the ones used to compile the prelude
599     # ToDo: get these options from a common definition in mkworld
600
601     # We also enable any options forced through with -user-prelude-force
602
603     # Hey, Check out this grep statement ;-)  (PS)
604
605     @ARGV = grep((!/^-O/ && !/^-f/ && !/^-user-prelude$/) || s/^-user-prelude-force//,
606                  @ARGV);
607
608     unshift(@ARGV,
609         '-fcompiling-ghc-internals=???', # ToDo!!!!
610         '-O',
611         '-fshow-pragma-name-errs',
612         '-fshow-import-specs',
613         '-fglasgow-exts',
614         '-genSPECS',
615         '-DUSE_FOLDR_BUILD',
616         '-dcore-lint');
617
618     print STDERR "ghc: -user-prelude options:\n", "@ARGV", "\n";
619 }
620
621 &initDriverGlobals();
622 &splitCmdLine(@ARGV);
623 # Run through the cmd-line first time.
624 &processArgs(@Cmd_opts);
625
626 # Check to see if driver is only in the business
627 # to generate dependencies
628 if (  $Status == 0 && $Only_generate_deps ) {
629
630     push (@MkDependHS_flags, "-o$Osuffix") if $Osuffix;
631     push (@MkDependHS_flags, "-s$BuildTag") if $BuildTag;
632     local($to_do) = "$MkDependHS @MkDependHS_flags -- @Cmd_opts -- @Input_file" ;
633     &run_something($to_do, 'Haskell dependencies');
634     exit $Status;
635 }
636
637 # if there are several input files,
638 # we don't allow \tr{-o <file>} or \tr{-ohi <file>} options...
639 # (except if linking, of course)
640
641 if ($#Input_file > 0 && ( ! $Do_lnkr )) {
642     if ( ($Specific_output_file ne '' && $Specific_output_file ne '-')
643       || ($Specific_hi_file ne ''     && $Specific_hi_file ne '-') ) {
644         print STDERR "$Pgm: You can't use -o or -ohi options if you have multiple input files.\n";
645         print STDERR "\tPerhaps the -odir option will do what you want.\n";
646         $Status++;
647     }
648 }
649
650 # check for various pathological -o and -odir combinations...
651 if ($Specific_output_dir ne '' && $Specific_output_file ne '') {
652     if ($Specific_output_file eq '-') {
653         print STDERR "$Pgm: can't set output directory with -ohi AND have output to stdout\n";
654         $Status++;
655     } else { # amalgamate...
656         $Specific_output_file = "$Specific_output_dir/$Specific_output_file";
657         # ToDo: check we haven't got a junk name now...
658         $Specific_output_dir  = ''; # reset
659     }
660 }
661
662 # crash and burn if there were errors
663 if ( $Status > 0 ) {
664     print STDERR $ShortUsage;
665     exit $Status;
666 }
667 \end{code}
668
669 %************************************************************************
670 %*                                                                      *
671 \section[Driver-post-argv-mangling]{Setup after reading options}
672 %*                                                                      *
673 %************************************************************************
674
675 %************************************************************************
676 %*                                                                      *
677 \subsection{Set up for optimisation level (\tr{-O} or whatever)}
678 %*                                                                      *
679 %************************************************************************
680
681 We come now to the default ``wads of options'' that are turned on by
682 \tr{-O0} (do min optimisation), \tr{-O} (ordinary optimisation),
683 \tr{-O2} (aggressive optimisation), or no O-ish flag (compile speed is
684 more important).
685
686 The user can also specify his/her own list of options in a file; in
687 that case, the work is already done (see stuff about @minusO3@,
688 earlier...).
689
690 GHC allows very precise control of what happens during a compilation.
691 Core-to-Core and STG-to-STG passes can be run in any order, as many
692 times as you like.  Individual transformations can be turned on or
693 disabled.
694
695 Sadly, however, there are some interdependencies \& Things You Must
696 Not Do.  Here is the list.
697
698 CORE-TO-CORE PASSES:
699 \begin{description}
700 \item[\tr{-fspecialise}:]
701 The specialiser must have dependency-analysed input; but if you run
702 the simplifier to do this, you must not let it toss away unused
703 bindings!  (The typechecker conveys some specialisation info via
704 ``unused'' bindings...)
705
706 \item[\tr{-ffloat-inwards}:]
707 Floating inwards should be done before strictness analysis, because
708 the latter will give better results.
709
710 \item[\tr{-fstatic-args}:]
711 The static-arguments-transformation pass {\em must} have the
712 simplifier run right after it.
713
714 \item[\tr{-fcalc-inlinings[12]}:]
715 Not required, but there may be slight gains by re-simplifying after
716 this is done.  (You could then \tr{-fcalc-inlinings} again, just for
717 fun.)
718
719 \item[\tr{-ffull-laziness}:]
720 The (outwards-)let-floater should be the {\em last} Core-to-Core pass
721 that's run.  (Um, well, howzabout the simplifier just once more...)
722 \end{description}
723
724 STG-TO-STG PASSES:
725 \begin{description}
726 \item[\tr{-fupdate-analysis}:]
727 It really really wants to be the last STG-to-STG pass that is run.
728 \end{description}
729
730 \begin{code}
731
732 sub setupOptimiseFlags {
733
734    @HsC_minusNoO_flags 
735     = ( '-fsimplify',
736           '\(',
737           $Oopt_FB_Support,
738 #         '-falways-float-lets-from-lets',      # no idea why this was here (WDP 95/09)
739           '-ffloat-lets-exposing-whnf',
740           '-ffloat-primops-ok',
741           '-fcase-of-case',
742 #         '-fdo-lambda-eta-expansion',  # too complicated
743           '-freuse-con',
744 #         '-flet-to-case',      # no strictness analysis, so...
745           $Oopt_PedanticBottoms,
746 #         $Oopt_MonadEtaExpansion,      # no thanks
747           '-fsimpl-uf-use-threshold0',
748           '-fessential-unfoldings-only',
749 #         $Oopt_UnfoldingUseThreshold,  # no thanks
750           $Oopt_MaxSimplifierIterations,
751           '\)',
752         $Oopt_AddAutoSccs,
753 #       '-ffull-laziness',      # removed 95/04 WDP following Andr\'e's lead
754         
755         $Oopt_FinalStgProfilingMassage
756       );
757
758    @HsC_minusO_flags # NOTE: used for *both* -O and -O2 (some conditional bits)
759     = (
760         '-fdo-eta-reduction',
761
762         # initial simplify: mk specialiser happy: minimum effort please
763         '-fsimplify',
764           '\(', 
765           $Oopt_FB_Support,
766           '-fkeep-spec-pragma-ids',     # required before specialisation
767           '-fsimpl-uf-use-threshold0',
768           '-fessential-unfoldings-only',
769           '-fmax-simplifier-iterations1',
770           $Oopt_PedanticBottoms,
771           '\)',
772
773         ($Oopt_DoSpecialise) ? (
774           '-fspecialise-overloaded',
775           $Oopt_SpecialiseUnboxed,
776           $Oopt_DoSpecialise,
777         ) : (),
778
779         '-fsimplify',                   # need dependency anal after specialiser ...
780           '\(',                         # need tossing before calc-inlinings ...
781           $Oopt_FB_Support,
782           '-ffloat-lets-exposing-whnf',
783           '-ffloat-primops-ok',
784           '-fcase-of-case',
785           '-fdo-case-elim',
786           '-fcase-merge',
787 #         '-fdo-eta-reduction',
788           '-fdo-lambda-eta-expansion',
789           '-freuse-con',
790           $Oopt_PedanticBottoms,
791           $Oopt_MonadEtaExpansion,
792           $Oopt_UnfoldingUseThreshold,
793           $Oopt_MaxSimplifierIterations,
794           '\)',
795
796 #LATER: '-fcalc-inlinings1', -- pointless for 2.01
797
798 #       ($Oopt_FoldrBuildWW) ? (
799 #               '-ffoldr-build-ww-anal',
800 #               '-ffoldr-build-worker-wrapper',
801 #               '-fsimplify', 
802 #                 '\(', 
803 #                 $Oopt_FB_Support,
804 #                 '-ffloat-lets-exposing-whnf',
805 #                 '-ffloat-primops-ok',
806 #                 '-fcase-of-case',
807 #                 '-fdo-case-elim',
808 #                 '-fcase-merge',
809 #                 '-fdo-eta-reduction',
810 #                 '-fdo-lambda-eta-expansion',
811 #                 '-freuse-con',
812 #                 $Oopt_PedanticBottoms,
813 #                 $Oopt_MonadEtaExpansion,
814 #                 $Oopt_UnfoldingUseThreshold,
815 #                 $Oopt_MaxSimplifierIterations,
816 #                 '\)',
817 #        ) : (),
818
819         # this pass-ordering sequence was agreed by Simon and Andr\'e
820         # (WDP 94/07, 94/11).
821         '-ffull-laziness',
822
823         ($Oopt_FoldrBuild) ? (
824           '-ffoldr-build-on',           # desugar list comprehensions for foldr/build
825
826           '-fsimplify', 
827             '\(', 
828             '-fignore-inline-pragma',   # **** NB!
829             '-fdo-foldr-build',         # NB
830             $Oopt_FB_Support,
831             '-ffloat-lets-exposing-whnf',
832             '-ffloat-primops-ok',
833             '-fcase-of-case',
834             '-fdo-case-elim',
835             '-fcase-merge',
836 #           '-fdo-eta-reduction',
837             '-fdo-lambda-eta-expansion',        # After full laziness
838             '-freuse-con',
839             $Oopt_PedanticBottoms,
840             $Oopt_MonadEtaExpansion,
841             $Oopt_UnfoldingUseThreshold,
842             $Oopt_MaxSimplifierIterations,
843             '\)',
844         ) : (),
845
846         '-ffloat-inwards',
847
848         '-fsimplify',
849           '\(', 
850           $Oopt_FB_Support,
851           '-ffloat-lets-exposing-whnf',
852           '-ffloat-primops-ok',
853           '-fcase-of-case',
854           '-fdo-case-elim',
855           '-fcase-merge',
856           '-fdo-eta-reduction',
857           '-fdo-lambda-eta-expansion',
858           '-freuse-con',
859           ($Oopt_FoldrBuildInline),
860                         # you need to inline foldr and build
861           ($Oopt_FoldrBuild) ? ('-fdo-foldr-build') : (), 
862                         # but do reductions if you see them!
863           $Oopt_PedanticBottoms,
864           $Oopt_MonadEtaExpansion,
865           $Oopt_UnfoldingUseThreshold,
866           $Oopt_MaxSimplifierIterations,
867           '\)',
868
869         '-fstrictness',
870
871         '-fsimplify',
872           '\(', 
873           $Oopt_FB_Support,
874           '-ffloat-lets-exposing-whnf',
875           '-ffloat-primops-ok',
876           '-fcase-of-case',
877           '-fdo-case-elim',
878           '-fcase-merge',
879 #         '-fdo-eta-reduction',
880           '-fdo-lambda-eta-expansion',
881           '-freuse-con',
882           '-flet-to-case',              # Aha! Only done after strictness analysis
883           $Oopt_PedanticBottoms,
884           $Oopt_MonadEtaExpansion,
885           $Oopt_UnfoldingUseThreshold,
886           $Oopt_MaxSimplifierIterations,
887           '\)',
888
889         '-ffloat-inwards',
890
891 # Case-liberation for -O2.  This should be after
892 # strictness analysis and the simplification which follows it.
893
894 #       ( ($OptLevel != 2)
895 #        ? ''
896 #       : "-fliberate-case -fsimplify \\( $Oopt_FB_Support -ffloat-lets-exposing-whnf -ffloat-primops-ok -fcase-of-case -fdo-case-elim -fcase-merge -fdo-eta-reduction -fdo-lambda-eta-expansion -freuse-con -flet-to-case $Oopt_PedanticBottoms $Oopt_MonadEtaExpansion $Oopt_UnfoldingUseThreshold $Oopt_MaxSimplifierIterations \\)" ),
897
898 # Final clean-up simplification:
899
900         '-fsimplify',
901           '\(', 
902           $Oopt_FB_Support,
903           '-ffloat-lets-exposing-whnf',
904           '-ffloat-primops-ok',
905           '-fcase-of-case',
906           '-fdo-case-elim',
907           '-fcase-merge',
908 #         '-fdo-eta-reduction',
909           '-fdo-lambda-eta-expansion',
910           '-freuse-con',
911           '-flet-to-case',
912           '-fignore-inline-pragma',     # **** NB!
913           $Oopt_FoldrBuildInline,       
914           ($Oopt_FoldrBuild) ? ('-fdo-foldr-build') : (), 
915                         # but still do reductions if you see them!
916           $Oopt_PedanticBottoms,
917           $Oopt_MonadEtaExpansion,
918           $Oopt_UnfoldingUseThreshold,
919           $Oopt_MaxSimplifierIterations,
920           '\)',
921
922       # '-fstatic-args',
923
924 #LATER: '-fcalc-inlinings2', -- pointless for 2.01
925
926       # stg2stg passes
927         '-fupdate-analysis',
928         '-flambda-lift',
929         $Oopt_FinalStgProfilingMassage,
930         $Oopt_StgStats,
931
932       # flags for stg2stg
933         '-flet-no-escape',
934
935       # SPECIAL FLAGS for -O2
936         ($OptLevel == 2) ? (
937           '-fsemi-tagging',
938         ) : (),
939       );
940
941 \end{code}
942
943 Sort out what we're going to do about optimising.  First, the @hsc@
944 flags and regular @cc@ flags to worry about:
945 \begin{code}
946 if ( $OptLevel <= 0 ) {
947
948     # for this level, we tell the parser -fignore-interface-pragmas
949     push(@HsC_flags, '-fignore-interface-pragmas');
950     # and tell the compiler not to produce them
951     push(@HsC_flags, '-fomit-interface-pragmas');
952
953     &add_Hsc_flags( @HsC_minusNoO_flags );
954     push(@CcBoth_flags, ($MinusO2ForC) ? '-O2' : '-O'); # not optional!
955
956 } elsif ( $OptLevel == 1 || $OptLevel == 2 ) {
957
958     &add_Hsc_flags( @HsC_minusO_flags );
959     push(@CcBoth_flags, ($MinusO2ForC || $OptLevel == 2) ? '-O2' : '-O'); # not optional!
960     # -O? to GCC is not optional! -O2 probably isn't worth it generally,
961     # but it *is* useful in compiling the garbage collectors (so said
962     # Patrick many moons ago...).
963
964 } else { # -Ofile, then...
965
966     &add_Hsc_flags( @HsC_minusO3_flags );
967     push(@CcBoth_flags, ($MinusO2ForC) ? '-O2' : '-O'); # possibly to be elaborated...
968 }
969
970 } # setupOptimiseFlags
971
972 \end{code}
973
974 %************************************************************************
975 %*                                                                      *
976 \subsection{Check for consistency, etc.}
977 %*                                                                      *
978 %************************************************************************
979
980 Sort out @$BuildTag@, @$PROFing@, @$CONCURing@, @$PARing@,
981 @$GRANing@, @$TICKYing@:
982 \begin{code}
983 sub setupBuildFlags {
984
985
986    # PROFILING stuff after argv mangling:
987    if ( ! $PROFing ) {
988      # warn about any scc exprs found (in case scc used as identifier)
989      push(@HsP_flags, '-W');
990
991      # add -auto sccs even if not profiling !
992      push(@HsC_flags, $UNPROFscc_auto) if $UNPROFscc_auto;
993
994    } else {
995       push(@HsC_flags, $PROFauto) if $PROFauto;
996       push(@HsC_flags, $PROFcaf)  if $PROFcaf;
997       #push(@HsC_flags, $PROFdict) if $PROFdict;
998
999       $Oopt_FinalStgProfilingMassage = '-fmassage-stg-for-profiling';
1000
1001       push(@HsP_flags, (($PROFignore_scc) ? $PROFignore_scc : '-S'));
1002
1003       if ( $SplitObjFiles ) {
1004          # can't split with cost centres -- would need global and externs
1005          print STDERR "$Pgm: WARNING: splitting objects when profiling will *BREAK* if any _scc_s are present!\n";
1006          # (but it's fine if there aren't any _scc_s around...)
1007 #        $SplitObjFiles = 0; # unset
1008          #not an error: for now: $Status++;
1009       }
1010   }
1011   #if ( $BuildTag ne '' ) {
1012   #    local($b) = $BuildDescr{$BuildTag};
1013   #    if ($CONCURing eq 'c') { print STDERR "$Pgm: Can't mix $b with -concurrent.\n"; exit 1; }
1014   #    if ($PARing    eq 'p') { print STDERR "$Pgm: Can't mix $b with -parallel.\n"; exit 1; }
1015   #    if ($GRANing   eq 'g') { print STDERR "$Pgm: Can't mix $b with -gransim.\n"; exit 1; }
1016   #    if ($TICKYing  eq 't') { print STDERR "$Pgm: Can't mix $b with -ticky.\n"; exit 1; }
1017
1018   #    # ok to have a user-way profiling build
1019   #    # eval the profiling opts ... but leave user-way BuildTag 
1020   #    if ($PROFing   eq 'p') { &processArgs(split(' ', $SetupOpts{'_p'})); } # eval($EvaldSetupOpts{'_p'}); }
1021
1022   if ( $PROFing eq 'p' ) {
1023       if ($PARing   eq 'p') { print STDERR "$Pgm: Can't do profiling with -parallel.\n"; exit 1; }
1024       if ($GRANing  eq 'g') { print STDERR "$Pgm: Can't do profiling with -gransim.\n"; exit 1; }
1025       if ($TICKYing eq 't') { print STDERR "$Pgm: Can't do profiling with -ticky.\n"; exit 1; }
1026       $BuildTag = ($CONCURing eq 'c') ? '_mr' : '_p' ; # possibly "profiled concurrent"...
1027
1028   } elsif ( $CONCURing eq 'c' ) {
1029       if ($PARing  eq 'p') { print STDERR "$Pgm: Can't mix -concurrent with -parallel.\n"; exit 1; }
1030       if ($GRANing eq 'g') { print STDERR "$Pgm: Can't mix -concurrent with -gransim.\n"; exit 1; }
1031       $BuildTag = ($TICKYing eq 't')  ? '_mt' : '_mc' ; # possibly "ticky concurrent"...
1032       # "profiled concurrent" already acct'd for...
1033
1034   } elsif ( $PARing eq 'p' ) {
1035       if ($GRANing  eq 'g') { print STDERR "$Pgm: Can't mix -parallel with -gransim.\n"; exit 1; }
1036       if ($TICKYing eq 't') { print STDERR "$Pgm: Can't mix -parallel with -ticky.\n"; exit 1; }
1037       $BuildTag = '_mp';
1038
1039       if ( $Do_lnkr && ( ! $ENV{'PVM_ROOT'} || ! $ENV{'PVM_ARCH'} )) {
1040           print STDERR "$Pgm: both your PVM_ROOT and PVM_ARCH environment variables must be set for linking under -parallel.\n";
1041           exit(1);
1042       }
1043
1044   } elsif ( $GRANing eq 'g' ) {
1045       if ($TICKYing eq 't') { print STDERR "$Pgm: Can't mix -gransim with -ticky.\n"; exit 1; }
1046       $BuildTag = '_mg';
1047
1048   } elsif ( $TICKYing eq 't' ) {
1049       $BuildTag = '_t';
1050   }
1051
1052 \end{code}
1053
1054 After the sanity checks, add flags to the necessary parts of the driver pipeline:
1055
1056 \begin{code}
1057   if ( $BuildTag ne '' ) { # something other than normal sequential...
1058
1059       local($Tag) = "${BuildTag}";
1060       $Tag =~ s/_//;  # move the underscore to the back
1061
1062       $HscOut = '-C='; # must go via C
1063       &processArgs(split(' ', $SetupOpts{$BuildTag}));
1064 #      eval($EvaldSetupOpts{$BuildTag});
1065   }
1066 \end{code}
1067
1068 Decide what the consistency-checking options are in force for this run:
1069 \begin{code}
1070
1071   $HsC_consist_options = "${BuildTag},${DEBUGging}";
1072   $Cc_consist_options  = "${BuildTag},${DEBUGging}";
1073
1074   #
1075   # Funny place to put it, but why not.
1076   #
1077   if ( $HiSuffix_prelude eq '' ) {
1078        local($Tag) = "${BuildTag}";
1079        $Tag =~ s/_//;
1080        $Tag = "${Tag}_" if $Tag ne '';
1081        $HiSuffix_prelude="${Tag}hi";
1082   }
1083   push(@HsC_flags, "-hisuf-prelude=.${HiSuffix_prelude}"); # use appropriate Prelude .hi files
1084   push(@HsC_flags, "-hisuf=.${HiSuffix}");
1085
1086 } # setupBuildFlags
1087 \end{code}
1088
1089 %************************************************************************
1090 %*                                                                      *
1091 \subsection{Add on machine-specific C-compiler flags}
1092 %*                                                                      *
1093 %************************************************************************
1094
1095 Shove on magical machine-specific options.  We use \tr{unshift} to
1096 stick them on the {\em front} of the arrays, so that ``later''
1097 user-specified flags can clobber them (e.g., \tr{-U__STG_REV_TBLS__}).
1098
1099 Note: a few ``always apply'' flags were set at the very beginning.
1100
1101 \begin{code}
1102 sub setupMachOpts {
1103
1104   if ($TargetPlatform =~ /^alpha-/) {
1105       # we know how to *mangle* asm for alpha
1106       unshift(@CcRegd_flags, ('-D__STG_REV_TBLS__'));
1107       unshift(@CcRegd_flags, ('-DSTACK_CHECK_BY_PAGE_FAULT=1')) if $StkChkByPageFaultOK;
1108       unshift(@CcBoth_flags,  ('-static'));
1109
1110   } elsif ($TargetPlatform =~ /^hppa/) {
1111       # we know how to *mangle* asm for hppa
1112       unshift(@CcRegd_flags, ('-D__STG_REV_TBLS__'));
1113       unshift(@CcBoth_flags,  ('-static'));
1114       #
1115       # We don't put in '-mlong-calls', because it's only
1116       # needed for very big modules (sigh), and we don't want
1117       # to hobble ourselves further on all the other modules
1118       # (most of them).
1119       #  
1120       # [Dated comment (gcc-2.6.x?), -mlong-calls is no longer
1121       #  a supported gcc HPPA flag]
1122       unshift(@CcBoth_flags,  ('-D_HPUX_SOURCE'));
1123         # ___HPUX_SOURCE, not _HPUX_SOURCE, is #defined if -ansi!
1124         # (very nice, but too bad the HP /usr/include files don't agree.)
1125
1126   } elsif ($TargetPlatform =~ /^i386-/) {
1127       # we know how to *mangle* asm for X86
1128       unshift(@CcRegd_flags, ('-D__STG_REV_TBLS__'));
1129       unshift(@CcRegd_flags, ('-DSTACK_CHECK_BY_PAGE_FAULT=1')) if $StkChkByPageFaultOK;
1130
1131       # -fno-defer-pop : basically the same game as for m68k
1132       #
1133       # -fomit-frame-pointer : *must* ; because we're stealing
1134       #  the fp (%ebp) for our register maps.  *All* register
1135       #  maps (in MachRegs.lh) must steal it.
1136
1137       unshift(@CcRegd_flags_hc, '-fno-defer-pop');
1138       unshift(@CcRegd_flags,    '-fomit-frame-pointer');
1139       unshift(@CcRegd_flags,    "-DSTOLEN_X86_REGS=$StolenX86Regs");
1140
1141   } elsif ($TargetPlatform =~ /^m68k-/) {
1142       # we know how to *mangle* asm for m68k
1143       unshift (@CcRegd_flags, ('-D__STG_REV_TBLS__'));
1144       unshift (@CcRegd_flags, ('-DSTACK_CHECK_BY_PAGE_FAULT=1')) if $StkChkByPageFaultOK;
1145
1146       # -fno-defer-pop : for the .hc files, we want all the pushing/
1147       #    popping of args to routines to be explicit; if we let things
1148       #    be deferred 'til after an STGJUMP, imminent death is certain!
1149       #
1150       # -fomit-frame-pointer : *don't*
1151       #    It's better to have a6 completely tied up being a frame pointer
1152       #    rather than let GCC pick random things to do with it.
1153       #    (If we want to steal a6, then we would try to do things
1154       #    as on iX86, where we *do* steal the frame pointer [%ebp].)
1155
1156       unshift(@CcRegd_flags_hc, '-fno-defer-pop');
1157       unshift(@CcRegd_flags,    '-fno-omit-frame-pointer');
1158         # maybe gives reg alloc a better time
1159         # also: -fno-defer-pop is not sufficiently well-behaved without it
1160
1161   } elsif ($TargetPlatform =~ /^mips-/) {
1162       # we (hope to) know how to *mangle* asm for MIPSen
1163       unshift(@CcRegd_flags, ('-D__STG_REV_TBLS__'));
1164       unshift(@CcRegd_flags, ('-DSTACK_CHECK_BY_PAGE_FAULT=1')) if $StkChkByPageFaultOK;
1165       unshift(@CcBoth_flags,  ('-static'));
1166
1167   } elsif ($TargetPlatform =~ /^powerpc-/) {
1168       # we know how to *mangle* asm for PowerPC
1169       unshift(@CcRegd_flags, ('-D__STG_REV_TBLS__'));
1170       unshift(@CcRegd_flags, ('-DSTACK_CHECK_BY_PAGE_FAULT=1')) if $StkChkByPageFaultOK;
1171       unshift(@CcBoth_flags,  ('-static')); # always easier to start with
1172       unshift(@CcRegd_flags, ('-finhibit-size-directive')); # avoids traceback tables
1173
1174   } elsif ($TargetPlatform =~ /^sparc-/) {
1175       # we know how to *mangle* asm for SPARC
1176       unshift(@CcRegd_flags, ('-D__STG_REV_TBLS__'));
1177       unshift(@CcRegd_flags, ('-DSTACK_CHECK_BY_PAGE_FAULT=1')) if $StkChkByPageFaultOK;
1178
1179   }
1180 } # end of setupMachOpts
1181 \end{code}
1182
1183 Same unshifting magic, but for special linker flags.
1184
1185 The configure script determines whether the object file symbol tables
1186 have a leading underscore, and sets @LeadingUnderscore@ accordingly.
1187 (The driver script `sees' the setting of the @LeadingUnderscore@
1188 by having the Makefile prepend it).
1189
1190 \begin{code}
1191 sub setupLinkOpts {
1192   local($uscore) = ( ${LeadingUnderscore} eq 'YES' ) ? '_' : '';
1193
1194   unshift(@Ld_flags,
1195         (($Ld_main) ? (
1196           '-u', "${uscore}Main_" . $Ld_main . '_closure',
1197         ) : ()
1198 # What are these? -- SOF
1199 #         , '-u', "${uscore}STbase_unsafePerformPrimIO_fast1"
1200 #         , '-u', "${uscore}Prelude_Z91Z93_closure"      # i.e., []
1201 #         , '-u', "${uscore}Prelude_IZh_static_info"
1202 #         , '-u', "${uscore}Prelude_False_inregs_info"
1203 #         , '-u', "${uscore}Prelude_True_inregs_info"
1204 #         , '-u', "${uscore}Prelude_CZh_static_info"
1205 #         , '-u', "${uscore}DEBUG_REGS"
1206         ))
1207          ; # just for fun, now...
1208
1209 } # end of setupLinkOpts
1210
1211 \end{code}
1212
1213 %************************************************************************
1214 %*                                                                      *
1215 \subsection{Set up include paths and system-library enslurpment}
1216 %*                                                                      *
1217 %************************************************************************
1218
1219 Now that we know what garbage-collector, etc., are required, we can
1220 finalise our list of libraries to slurp through, and generally Get
1221 Ready for Business.
1222
1223 \begin{code}
1224 sub setupIncPaths {
1225   # default includes must be added AFTER option processing
1226   if ( ! $INSTALLING ) {
1227       push (@Include_dir, "$TopPwd/${CURRENT_DIR}/${GHC_INCLUDE_DIR}");
1228   } else {
1229       push (@Include_dir, "$InstLibDirGhc/includes");
1230       push (@Include_dir, "$InstLibDirGhc/includes");
1231   }
1232 } # end of setupIncPaths
1233 \end{code}
1234
1235 \begin{code}
1236 sub setupSyslibs {
1237   push(@SysLibrary, ( '-lHS', '-lHS_cbits' )); # basic I/O and prelude stuff
1238
1239   local($f);
1240   foreach $f (@SysLibrary) {
1241       next if $f =~ /_cbits/;
1242       $f .= $BuildTag if $f =~ /^-lHS/;
1243   }
1244
1245   # fiddle the TopClosure file name...
1246   $TopClosureFile =~ s/XXXX//;
1247
1248   # Push library HSrts, plus boring clib bit
1249   push(@SysLibrary, "-lHSrts${BuildTag}");
1250   push(@SysLibrary, '-lHSclib');
1251   #
1252   # RTS compiled with cygwin32, uses the WinMM API
1253   # to implement the itimers, since cygwin.dll does not
1254   # support it. Only reqd. for `ways' that use itimers.
1255   #
1256   push(@SysLibrary, '-lwinmm') if $BuildTag ne '' && $TargetPlatform eq 'i386-unknown-cygwin32';
1257
1258   # Push the pvm libraries
1259   if ($BuildTag eq '_mp') {
1260       $pvmlib = "$ENV{'PVM_ROOT'}/lib/$ENV{'PVM_ARCH'}";
1261       push(@SysLibrary, "-L$pvmlib", '-lpvm3', '-lgpvm3');
1262       if ( $ENV{'PVM_ARCH'} eq 'SUNMP' ) {
1263           push(@SysLibrary, '-lthread', '-lsocket', '-lnsl');
1264       } elsif ( $ENV{'PVM_ARCH'} eq 'SUN4SOL2' ) {
1265           push(@SysLibrary, '-lsocket', '-lnsl');
1266       }
1267   }
1268
1269 # Push the GNU multi-precision arith lib; and the math library
1270 push(@SysLibrary, '-lgmp');
1271 push(@SysLibrary, '-lm');
1272 \end{code}
1273
1274 %************************************************************************
1275 %*                                                                      *
1276 \subsection{Check that this system was built to do what we are asking}
1277 %*                                                                      *
1278 %************************************************************************
1279
1280 Before continuing we check that the appropriate build is available.
1281
1282 \begin{code}
1283 #die "$Pgm: no BuildAvail?? $BuildTag\n" if $BuildDescr{$BuildTag} eq '' ; # sanity
1284
1285 if ( $BuildDescr{$BuildTag} eq '' ) {
1286     print STDERR "$Pgm: a `", $BuildDescr{$BuildTag},
1287         "' \"build\" is not available with your GHC setup.\n";
1288     print STDERR "(It was not configured for it at your site.)\n";
1289     print STDERR $ShortUsage;
1290     exit 1;
1291 }
1292
1293 } # end of setupSyslibs
1294
1295 \end{code}
1296
1297 %************************************************************************
1298 %*                                                                      *
1299 \subsection{Final miscellaneous setup bits before we start going}
1300 %*                                                                      *
1301 %************************************************************************
1302
1303 Record largest specific heapsize, if any.
1304 \begin{code}
1305 sub setupHeapStackSize {
1306    $Specific_heap_size = $Specific_heap_size * $Scale_sizes_by;
1307    push(@HsC_rts_flags, '-H'.$Specific_heap_size);
1308    $Specific_stk_size = $Specific_stk_size * $Scale_sizes_by;
1309    push(@HsC_rts_flags, "-K$Specific_stk_size");
1310 }
1311 \end{code}
1312
1313 If no input or link files seen, then we let 'em feed in stdin; this is
1314 mainly for debugging.
1315
1316 \begin{code}
1317
1318 if ($#Input_file < 0 && $#Link_file < 0) {
1319     @Input_file = ( '-' );
1320
1321     open(INF, "> $Tmp_prefix.hs") || &tidy_up_and_die(1,"Can't open $Tmp_prefix.hs\n");
1322     print STDERR "Enter your Haskell program, end with ^D (on a line of its own):\n";
1323     while (<>) { print INF $_; }
1324     close(INF) || &tidy_up_and_die(1,"Failed writing to $Tmp_prefix.hs\n");
1325 }
1326
1327 \end{code}
1328
1329 Tell the world who we are, if they asked.
1330 \begin{code}
1331 print STDERR "${PROJECTNAME}, version ${PROJECTVERSION}, patchlevel ${PROJECTPATCHLEVEL}\n"
1332     if $Verbose;
1333 \end{code}
1334
1335 %************************************************************************
1336 %*                                                                      *
1337 \section[Driver-main-loop]{Main loop: Process input files, and link if required}
1338 %*                                                                      *
1339 %************************************************************************
1340
1341 Process the input files; don't continue with linking if there are
1342 problems (global variable @$Status@ non-zero).
1343 \begin{code}
1344 foreach $ifile (@Input_file) {
1345     &ProcessInputFile($ifile);
1346 }
1347
1348 if ( $Status > 0 ) { # don't link if there were errors...
1349     print STDERR $ShortUsage;
1350     &tidy_up();
1351     exit $Status;
1352 }
1353
1354 # append last minute flags linker and consistency flags
1355 &setupBuildFlags();
1356 &setupSyslibs();
1357 &setupLinkOpts();
1358
1359 \end{code}
1360
1361 Link if appropriate.
1362 \begin{code}
1363 if ($Do_lnkr) {
1364     local($libdirs) = '';
1365
1366     # glue them together:
1367     push(@UserLibrary_dir, @SysLibrary_dir);
1368
1369     $libdirs = '-L' . join(' -L',@UserLibrary_dir) if $#UserLibrary_dir >= 0;
1370
1371     # for a linker, use an explicitly given one, or the going C compiler ...
1372     local($lnkr) = ( $Lnkr ) ? $Lnkr : $CcRegd;
1373
1374     local($output) = ($Specific_output_file ne '') ? "-o $Specific_output_file" : '';
1375     @Files_to_tidy = ($Specific_output_file ne '') ? $Specific_output_file : 'a.out';
1376
1377     local($to_do) = "$lnkr $Verbose @Ld_flags $output @Link_file $TopClosureFile $libdirs @UserLibrary @SysLibrary";
1378     &run_something($to_do, 'Linker');
1379
1380     # finally, check the consistency info in the binary
1381     local($executable) = $Files_to_tidy[0];
1382     @Files_to_tidy = (); # reset; we don't want to nuke it if it's inconsistent
1383
1384     if ( $LinkChk ) {
1385         # dynamically load consistency-chking code; then do it.
1386         require('ghc-consist.prl')
1387             || &tidy_up_and_die(1,"$Pgm: panic: can't load ghc-consist.prl!\n");
1388
1389         &chk_consistency_info ( $executable );
1390     }
1391
1392     # if PVM parallel stuff, we do truly weird things.
1393     # Essentially: (1) move the executable over to where PVM expects
1394     # to find it.  (2) create a script in place of the executable
1395     # which will cause the program to be run, via SysMan.
1396     if ( $PARing eq 'p' ) {
1397         local($pvm_executable) = $executable;
1398         local($pvm_executable_base);
1399
1400         if ( $pvm_executable !~ /^\// ) { # a relative path name: make absolute
1401             local($pwd) = `pwd`;
1402             chop($pwd);
1403             $pwd =~ s/^\/tmp_mnt//;
1404             $pvm_executable = "$pwd/$pvm_executable";
1405         }
1406
1407         $pvm_executable =~ s|/|=|g; # make /s into =s
1408         $pvm_executable_base = $pvm_executable;
1409
1410         $pvm_executable = $ENV{'PVM_ROOT'} . '/bin/' . $ENV{'PVM_ARCH'}
1411                         . "/$pvm_executable";
1412
1413         &run_something("$Rm -f $pvm_executable; $Cp -p $executable $pvm_executable && $Rm -f $executable", 'Moving binary to PVM land');
1414
1415         # OK, now create the magic script for "$executable"
1416         open(EXEC, "> $executable") || &tidy_up_and_die(1,"$Pgm: couldn't open $executable to write!\n");
1417         print EXEC <<EOSCRIPT1;
1418 eval 'exec perl -S \$0 \${1+"\$@"}'
1419   if \$running_under_some_shell;
1420 # =!=!=!=!=!=!=!=!=!=!=!
1421 # This script is automatically generated: DO NOT EDIT!!!
1422 # Generated by Glasgow Haskell, version ${PROJECTVERSION} ${PROJECTPATCHLEVEL}
1423 #
1424 \$pvm_executable      = '$pvm_executable';
1425 \$pvm_executable_base = '$pvm_executable_base';
1426 \$SysMan = '$SysMan';
1427 EOSCRIPT1
1428
1429         print EXEC <<\EOSCRIPT2;
1430 # first, some magical shortcuts to run "commands" on the binary
1431 # (which is hidden)
1432 if ($#ARGV == 1 && $ARGV[0] eq '+RTS' && $ARGV[1] =~ /^--((size|file|strip|rm|nm).*)/ ) {
1433     local($cmd) = $1;
1434     system("$cmd $pvm_executable");
1435     exit(0); # all done
1436 }
1437
1438 # OK, really run it; process the args first
1439 $ENV{'PE'} = $pvm_executable_base;
1440 $debug = '';
1441 $nprocessors = 2; # the default
1442 @nonPVM_args = ();
1443 $in_RTS_args = 0;
1444
1445 # ToDo: handle --RTS
1446 args: while ($a = shift(@ARGV)) {
1447     if ( $a eq '+RTS' ) {
1448         $in_RTS_args = 1;
1449     } elsif ( $a eq '-RTS' ) {
1450         $in_RTS_args = 0;
1451     }
1452     if ( $a eq '-d' && $in_RTS_args ) {
1453         $debug = '-';
1454     } elsif ( $a =~ /^-N(\d+)/ && $in_RTS_args ) {
1455         $nprocessors = $1;
1456     } else {
1457         push(@nonPVM_args, $a);
1458     }
1459 }
1460
1461 local($return_val) = 0;
1462 system("$SysMan $debug $pvm_executable $nprocessors @nonPVM_args");
1463 $return_val = $?;
1464 system("mv $ENV{'HOME'}/$pvm_executable_base.???.gr .") if -f "$ENV{'HOME'}/$pvm_executable_base.001.gr";
1465 exit($return_val);
1466 EOSCRIPT2
1467         close(EXEC) || die "Failed closing $executable\n";
1468         chmod 0755, $executable;
1469     }
1470 }
1471
1472 # that...  that's all, folks!
1473 &tidy_up();
1474 exit $Status; # will still be 0 if all went well
1475 \end{code}
1476
1477 %************************************************************************
1478 %*                                                                      *
1479 \section[Driver-do-one-file]{How to process a single input file}
1480 %*                                                                      *
1481 %************************************************************************
1482
1483 \begin{code}
1484 sub ProcessInputFile {
1485     local($ifile) = @_;   # input file name
1486     local($ifile_root);   # root of or basename of input file
1487     local($ofile_target); # ultimate output file we hope to produce
1488                           # from input file (need to know for recomp
1489                           # checking purposes)
1490     local($hifile_target);# ditto (but .hi file)
1491 \end{code}
1492
1493 Handle the weirdity of input from stdin.
1494 \begin{code}
1495     if ($ifile ne '-') {
1496         ($ifile_root  = $ifile) =~ s/\.[^\.\/]+$//;
1497         $ofile_target = # may be reset later...
1498                         ($Specific_output_file ne '' && ! $Do_lnkr)
1499                         ? $Specific_output_file
1500                         : &odir_ify($ifile_root, 'o');
1501         $hifile_target= ($Specific_hi_file ne '')
1502                         ? $Specific_hi_file
1503                         : "$ifile_root.$HiSuffix"; # ToDo: odirify?
1504                         # NB: may change if $ifile_root isn't module name (??)
1505     } else {
1506         $ifile = "$Tmp_prefix.hs"; # we know that's where we put the input
1507         $ifile_root   = '_stdin';
1508         $ofile_target = '_stdout'; # gratuitous?
1509         $hifile_target= '_stdout'; # ditto?
1510     }
1511 \end{code}
1512
1513 We need to decide what phases of the compilation system we will run
1514 over this file.  The defaults are the ones established when processing
1515 flags.  (That established what the last phase run for all files is.)
1516
1517 We do the pre-recompilation-checker phases here; the rest later.
1518 \begin{code}
1519 \end{code}
1520
1521 Look at the suffix and decide what initial phases of compilation may
1522 be dropped off for this file.  Also the rather boring business of
1523 which files are coming-in/going-out.
1524
1525 Again, we'll do the post-recompilation-checker parts of this later.
1526 \begin{code}
1527     local($do_lit2pgm)  = ($ifile =~ /\.lhs$/) ? 1 : 0;
1528     local($do_hscpp)    = 1; # but "hscpp" might really be "cat"
1529     local($do_hsc)      = 1;
1530
1531     # names of the files to stuff between phases
1532     # defaults are temporaries
1533     local($in_lit2pgm)    = $ifile;
1534     local($lit2pgm_hscpp) = "$Tmp_prefix.lpp";
1535     local($hscpp_hsc)     = "$Tmp_prefix.cpp";
1536     local($hsc_hi)        = "$Tmp_prefix.hi";
1537     local($cc_as_o)       = "${Tmp_prefix}_o.s"; # temporary for raw .s file if opt C
1538     local($cc_as)         = "$Tmp_prefix.s";     # mangled or hsc-produced .s code
1539     local($as_out)        = $ofile_target;
1540
1541     local($is_hc_file) = 1; #Is the C code .hc or .c? Assume .hc for now
1542
1543     $lit2pgm_hscpp = $ifile if ($ifile =~ /\.hs$/);
1544
1545     # OK, let's strip off some literate junk:
1546     &runLit2pgm($in_lit2pgm, $lit2pgm_hscpp) if ($ifile =~ /\.lhs$/);
1547     #
1548     @File_options = ();
1549
1550     # Scan the top of the de-litted file for {-# OPTIONS #-} pragmas
1551     &check_for_source_options($lit2pgm_hscpp);
1552     # options found in the source file take a back seat, i.e., we scan
1553     # them first. Only process the command line again if source file
1554     # contained anything of interest *or* there's more than one
1555     # input file (we have to reset the options).
1556     #
1557     if ( $#Input_file >= 0 || $#File_options >= 0) {
1558         @File_options = (@File_options, @Cmd_opts);
1559
1560         # Now process the command line
1561         &initDriverGlobals();
1562         &processArgs(@File_options);
1563     }
1564     #
1565     # Having got the effective command line scanned, set up
1566     # the various options in prep for some real work.
1567     #
1568     # check the sanity of the BuildTag we're about to use,
1569     # and if needs be, add some more flags and setup to
1570     # the different phases.
1571     #
1572     &setupBuildFlags();
1573     &setupOptimiseFlags();
1574     &setupMachOpts();
1575     &setupIncPaths();
1576     &setupHeapStackSize();
1577
1578     #
1579     # These two variables need to be set after the
1580     # command-line has been processed and the build options
1581     # have be seen set up. This is because command-line options
1582     # can control whether to compile vias C or not.
1583     # 
1584     local($do_cc)       = ( $Do_cc != -1) # i.e., it was set explicitly
1585                           ? $Do_cc
1586                           : ( ($HscOut eq '-C=') ? 1 : 0 );
1587     local($do_as)       = $Do_as;
1588     local($hsc_out)       = ( $HscOut eq '-C=' ) ? "$Tmp_prefix.hc" : "$Tmp_prefix.s" ;
1589
1590     if ($ifile =~ /.lhs$/ || $ifile =~ /.hs$/ ) {
1591        ;
1592     } elsif ($ifile =~ /\.hc$/ || $ifile =~ /_hc$/ ) { # || $ifile =~ /\.$Isuffix$/o) # ToDo: better
1593         $do_hscpp = 0; $do_hsc = 0; $do_cc = 1;
1594         $hsc_out = $ifile;
1595     } elsif ($ifile =~ /\.c$/) {
1596         $do_hscpp = 0; $do_hsc = 0; $do_cc = 1;
1597         $hsc_out = $ifile; $is_hc_file = 0;
1598     } elsif ($ifile =~ /\.s$/) {
1599         $do_hscpp = 0; $do_hsc = 0; $do_cc = 0;
1600         $cc_as = $ifile;    
1601     } else { # don't know what it is, but nothing to do herein...
1602         $do_hscpp = 0; $do_hsc = 0; $do_cc = 0; $do_as = 0;
1603     }
1604
1605     # hack to avoid running hscpp
1606     $HsCpp = $Cat if ! $Cpp_flag_set;
1607
1608     &runHscpp($in_lit2pgm, $lit2pgm_hscpp, $hscpp_hsc)
1609         if $do_hscpp;
1610 \end{code}
1611
1612 We now think about whether to run hsc/cc or not (when hsc produces .s
1613 stuff, it effectively takes the place of both phases).
1614
1615 To get the output file name right: for each phase that we are {\em
1616 not} going to run, set its input (i.e., the output of its preceding
1617 phase) to @"$ifile_root.<suffix>"@.
1618 \begin{code}
1619     local($going_interactive) = $HscOut eq '-N=' || $ifile_root eq '_stdin';
1620
1621     #
1622     # Warning issued if -keep-hc-file-too is used without
1623     # -fvia-C (or the equivalent)
1624     #
1625     if ( $HscOut ne '-C=' && $Keep_hc_file_too ) {
1626         print STDERR "Warning: Native code generator to be used, -keep-hc-file-too will be ignored\n";
1627     }
1628
1629     if (! $do_cc && ! $do_as) { # stopping after hsc
1630         $hsc_out = ($Specific_output_file ne '')
1631                  ? $Specific_output_file
1632                  : &odir_ify($ifile_root, ($HscOut eq '-C=') ? 'hc' : 's');
1633
1634         $ofile_target = $hsc_out; # reset
1635     }
1636
1637     if (! $do_as) { # stopping after gcc (or hsc)
1638         $cc_as = ($Specific_output_file ne '')
1639                  ? $Specific_output_file
1640                  : &odir_ify($ifile_root, ( $Only_preprocess_C ) ? 'i' : 's');
1641
1642         $ofile_target = $cc_as; # reset
1643     }
1644
1645 \end{code}
1646
1647
1648 Now the Haskell compiler, C compiler, and assembler
1649
1650 \begin{code}
1651    if ($do_hsc) {
1652         &runHscAndProcessInterfaces( $ifile, $hscpp_hsc, $ifile_root, 
1653                                      $ofile_target, $hifile_target);
1654     }
1655
1656     if ($do_cc) {
1657         &runGcc    ($is_hc_file, $hsc_out, $cc_as_o);
1658         &runMangler($is_hc_file, $cc_as_o, $cc_as, $ifile_root);
1659     }
1660
1661     &split_asm_file($cc_as)  if $do_as && $SplitObjFiles;
1662
1663     &runAs($as_out, $ifile_root) if $do_as;
1664 \end{code}
1665
1666 Finally, decide what to queue up for linker input.
1667 \begin{code}
1668     # tentatively assume we will eventually produce linker input:
1669     push(@Link_file, &odir_ify($ifile_root, 'o'));
1670
1671 #ToDo:    local($or_isuf) = ($Isuffix eq '') ? '' : "|$Isuffix";
1672
1673     if ( $ifile !~ /\.(lhs|hs|hc|c|s)$/ && $ifile !~ /_hc$/ ) {
1674         print STDERR "$Pgm: don't recognise suffix on `$ifile'; passing it through to linker\n"
1675             if $ifile !~ /\.a$/;
1676
1677         # oops; we tentatively pushed the wrong thing; fix & do the right thing
1678         pop(@Link_file); push(@Link_file, $ifile);
1679     }
1680
1681
1682 } # end of ProcessInputFile
1683 \end{code}
1684
1685 %************************************************************************
1686 %*                                                                      *
1687 \section[Driver-run-phases]{Routines to run the various phases}
1688 %*                                                                      *
1689 %************************************************************************
1690
1691 \begin{code}
1692 sub runLit2pgm {
1693     local($in_lit2pgm, $lit2pgm_hscpp) = @_;
1694
1695     local($to_do) = "echo '#line 1 \"$in_lit2pgm\"' > $lit2pgm_hscpp && ".
1696                     "$Unlit @Unlit_flags $in_lit2pgm -  >> $lit2pgm_hscpp";
1697     @Files_to_tidy = ( $lit2pgm_hscpp );
1698
1699     &run_something($to_do, 'literate pre-processor');
1700 }
1701 \end{code}
1702
1703 \begin{code}
1704 sub runHscpp {
1705     local($in_lit2pgm, $lit2pgm_hscpp, $hscpp_hsc) = @_;
1706
1707     local($to_do);
1708
1709     if ($HsCpp eq $Cat) {
1710         $to_do = "echo '#line 1 \"$in_lit2pgm\"' > $hscpp_hsc && ".
1711                         "$HsCpp $lit2pgm_hscpp >> $hscpp_hsc";
1712         @Files_to_tidy = ( $hscpp_hsc );
1713         &run_something($to_do, 'Ineffective C pre-processor');
1714     } else {
1715         local($includes) = '-I' . join(' -I',@Include_dir);
1716         $to_do = "echo '#line 1 \"$in_lit2pgm\"' > $hscpp_hsc && ".
1717                         "$HsCpp $Verbose $genSPECS_flag @HsCpp_flags -D__HASKELL1__=$Haskell1Version -D__GLASGOW_HASKELL__=$GhcVersionInfo $includes $lit2pgm_hscpp >> $hscpp_hsc";
1718         @Files_to_tidy = ( $hscpp_hsc );
1719         &run_something($to_do, 'Haskellised C pre-processor');
1720     }
1721 }
1722 \end{code}
1723
1724
1725 \begin{code}
1726 sub runHscAndProcessInterfaces {
1727     local($ifile, $hscpp_hsc, $ifile_root, $ofile_target, $hifile_target) = @_;
1728
1729         # $ifile                is the original input file
1730         # $hscpp_hsc            post-unlit, post-cpp, etc., input file
1731         # $ifile_root           input filename minus suffix
1732         # $ofile_target         the output file that we ultimately hope to produce
1733         # $hifile_target        the .hi file ... (ditto)
1734         
1735     local($source_unchanged) = 1;
1736
1737 # Check if the source file is up to date relative to the target; in
1738 # that case we say "source is unchanged" and let the compiler bail out
1739 # early if the import usage information allows it.
1740
1741     ($i_dev,$i_ino,$i_mode,$i_nlink,$i_uid,$i_gid,$i_rdev,$i_size,
1742      $i_atime,$i_mtime,$i_ctime,$i_blksize,$i_blocks) = stat($ifile);
1743
1744     if ( ! -f $ofile_target ) {
1745 #       print STDERR "$Pgm:compile:Output file $ofile_target doesn't exist\n";
1746         $source_unchanged = 0;
1747     }
1748
1749     ($o_dev,$o_ino,$o_mode,$o_nlink,$o_uid,$o_gid,$o_rdev,$o_size,
1750      $o_atime,$o_mtime,$o_ctime,$o_blksize,$o_blocks) = stat(_); # stat info from -f test
1751
1752     if ( ! -f $hifile_target ) {
1753 #       print STDERR "$Pgm:compile:Interface file $hifile_target doesn't exist\n";
1754         $source_unchanged = 0;
1755     }
1756
1757     ($hi_dev,$hi_ino,$hi_mode,$hi_nlink,$hi_uid,$hi_gid,$hi_rdev,$hi_size,
1758      $hi_atime,$hi_mtime,$hi_ctime,$hi_blksize,$hi_blocks) = stat(_); # stat info from -f test
1759
1760     if ($i_mtime > $o_mtime) {
1761 #       print STDERR "$Pgm:recompile:Input file $ifile newer than $ofile_target\n";
1762         $source_unchanged = 0;
1763     }
1764
1765     # So if source_unchanged is still "1", we pass on the good news to the compiler
1766     # The -recomp flag can disable this, forcing recompilation
1767     if ($Do_recomp_chkr && $source_unchanged) {
1768         push(@HsC_flags, '-fsource-unchanged'); 
1769     }   
1770
1771 # Run the compiler
1772
1773     &runHsc($ifile_root, $hsc_out, $hsc_hi, $going_interactive);
1774
1775 # See if it bailed out early, saying nothing needed doing.  
1776 # We work this out by seeing if it created an output .hi file
1777
1778     if ( ! -f $hsc_hi ) {
1779         # Doesn't exist, so we bailed out early.
1780         # Tell the C compiler and assembler not to run
1781         $do_cc = 0; $do_as = 0;
1782
1783         # Update dependency info, touch both object file and 
1784         # interface file, so that the following invariant is
1785         # maintained:
1786         #
1787         #   a dependent module's interface file should after recompilation
1788         #   checking be newer than the interface files of its imports. 
1789         #
1790         # That is, if module A's interface file changes, then module B
1791         # (which import from A) needs to be checked.
1792         # If A's change does not affect B, which causes the compiler to bail
1793         # out early, we still need to touch the interface file of B. The reason
1794         # for this is that B may export A's interface.
1795         #
1796         &run_something("touch $ofile_target $hifile_target", 
1797                        "Touch $ofile_target $hifile_target,  to propagate dependencies");
1798
1799     } else {    
1800
1801      # Didn't bail out early (new .hi file) so we thunder on
1802     
1803         # If non-interactive, heave in the consistency info at the end
1804         # NB: pretty hackish (depends on how $output is set)
1805         if ( ! $going_interactive ) {
1806             if ( $HscOut eq '-C=' ) {
1807             $to_do = "echo 'static char ghc_hsc_ID[] = \"\@(#)hsc $ifile\t$HsC_major_version.$HsC_minor_version,$HsC_consist_options\";' >> $hsc_out";
1808     
1809             } elsif ( $HscOut eq '-S=' ) {
1810                 local($consist) = "hsc.$ifile.$HsC_major_version.$HsC_minor_version.$HsC_consist_options";
1811                 $consist =~ s/,/./g;
1812                 $consist =~ s/\//./g;
1813                 $consist =~ s/-/_/g;
1814                 $consist =~ s/[^A-Za-z0-9_.]/ZZ/g; # ToDo: properly?
1815                 $to_do = "echo '\n\t.text\n$consist:' >> $hsc_out";
1816             }
1817             &run_something($to_do, 'Pin on Haskell consistency info');  
1818         }   
1819
1820
1821         # Interface-handling is important enough to live off by itself
1822         require('ghc-iface.prl')
1823             || &tidy_up_and_die(1,"$Pgm: panic: can't load ghc-iface.prl!\n");
1824         
1825         &postprocessHiFile($hsc_hi, $hifile_target, $going_interactive);
1826         
1827         # save a copy of the .hc file, even if we are carrying on...
1828         if ($HscOut eq '-C=' && $do_cc && $Keep_hc_file_too) {
1829             local($to_do) = "$Rm $ifile_root.hc; $Cp $hsc_out $ifile_root.hc";
1830             &run_something($to_do, 'Saving copy of .hc file');
1831         }
1832         
1833         # save a copy of the .s file, even if we are carrying on...
1834         if ($HscOut eq '-S=' && $do_as && $Keep_s_file_too) {
1835             local($to_do) = "$Rm $ifile_root.s; $Cp $hsc_out $ifile_root.s";
1836             &run_something($to_do, 'Saving copy of .s file');
1837         }
1838         
1839         # if we're going to split up object files,
1840         # we inject split markers into the .hc file now
1841         if ( $HscOut eq '-C=' && $SplitObjFiles ) {
1842             &inject_split_markers ( $hsc_out );
1843         }
1844     }
1845 }
1846 \end{code}
1847
1848
1849 \begin{code}
1850 sub runHsc {
1851     local($ifile_root, $hsc_out, $hsc_hi, $going_interactive) = @_;
1852
1853     # prepend comma to HsP flags (so hsc can tell them apart...)
1854     foreach $a ( @HsP_flags ) { $a = ",$a" unless $a =~ /^,/; }
1855
1856     &makeHiMap() unless $HiMapDone;
1857 #    print STDERR "HiIncludes: $HiIncludeString\n";
1858     push(@HsC_flags, "-himap=$HiIncludeString");
1859 #    push(@HsC_flags, "-himap=$HiMapFile");
1860
1861     # here, we may produce .hc/.s and/or .hi files
1862     local($output) = '';
1863     @Files_to_tidy = ();
1864
1865     if ( $going_interactive ) {
1866         # don't need .hi unless going to show it on stdout:
1867         $ProduceHi = '-nohifile=' if ! $HiOnStdout;
1868         $do_cc = 0; $do_as = 0; $Do_lnkr = 0; # and we won't go any further...
1869     }
1870
1871     # set up for producing output/.hi; note that flag twiddling
1872     # may mean that nothing will actually be produced:
1873     $output = "$ProduceHi$hsc_hi $HscOut$hsc_out";
1874     @Files_to_tidy = ( $hsc_hi, $hsc_out );
1875
1876     # if we're compiling foo.hs, we want the GC stats to end up in foo.stat
1877     if ( $CollectingGCstats ) {
1878         push(@HsC_rts_flags, "-S$ifile_root.stat");
1879         push(@Files_to_tidy, "$ifile_root.stat");
1880     }
1881
1882     if ( $CollectGhcTimings ) { # assume $RTS_style eq 'ghc'
1883         # emit nofibbish time/bytes-alloc stats to stderr;
1884         # see later .stat file post-processing
1885         push(@HsC_rts_flags, "-s$Tmp_prefix.stat");
1886         push(@Files_to_tidy, "$Tmp_prefix.stat");
1887     }
1888
1889     local($dump) = '';
1890     if ($Specific_dump_file ne '') {
1891         $dump = "2>> $Specific_dump_file";
1892         $Using_dump_file = 1;
1893     }
1894
1895     local($to_do);
1896     $to_do = "$HsC @HsP_flags ,$hscpp_hsc $dump @HsC_flags $CoreLint $StgLint $Verbose $output +RTS @HsC_rts_flags";
1897     &run_something($to_do, 'Haskell compiler');
1898
1899     # finish business w/ nofibbish time/bytes-alloc stats
1900     &process_ghc_timings() if $CollectGhcTimings;
1901 }
1902 \end{code}
1903
1904 Use \tr{@Import_dir} and \tr{@SysImport_dir} to make a tmp file
1905 of (module-name, pathname) pairs, one per line, separated by a space.
1906 \begin{code}
1907 #%HiMap     = ();
1908 $HiMapDone = 0;
1909 $HiMapFile = '';
1910 $HiIncludeString = ();          # dir1:dir2:dir3, to pass to GHC
1911
1912 sub makeHiMap {
1913
1914     # collect in %HiMap; write later; also used elsewhere in driver
1915
1916     local($mod, $path, $d, $e);
1917
1918     # reset the global variables:
1919     #%HiMap     = ();
1920     $HiMapDone = 0;
1921     $HiMapFile = '';
1922     $HiIncludeString = ();              # dir1:dir2:dir3, to pass to GHC
1923     
1924     foreach $d ( @Import_dir ) {
1925         if ($HiIncludeString) { $HiIncludeString = "$HiIncludeString:$d";
1926         } else { $HiIncludeString = $d; }
1927
1928 # The compiler does the searching now
1929 #
1930 #       opendir(DIR, $d) || &tidy_up_and_die(1,"$Pgm: error when reading directory: $d\n");
1931 #       local(@entry) = readdir(DIR);
1932 #       foreach $e ( @entry ) {
1933 #           next unless $e =~ /\b([A-Z][A-Za-z0-9_]*)\.${HiSuffix_prelude}$/o;
1934 #           $mod  = $1;
1935 #           $path = "$d/$e";
1936 #           $path =~ s,^\./,,;
1937 #
1938 #           if ( ! defined($HiMap{$mod}) ) {
1939 #               $HiMap{$mod} = $path;
1940 #           } else {
1941 #               &already_mapped_err($mod, $HiMap{$mod}, $path);
1942 #           }
1943 #       }
1944 #       closedir(DIR); # || &tidy_up_and_die(1,"$Pgm: error when closing directory: $d\n");
1945     }
1946
1947     foreach $d ( @SysImport_dir ) {
1948         if ($HiIncludeString) { $HiIncludeString = "$HiIncludeString:$d";
1949         } else { $HiIncludeString = $d; }
1950
1951 #       opendir(DIR, $d) || &tidy_up_and_die(1,"$Pgm: error when reading directory: $d\n");
1952 #       local(@entry) = readdir(DIR);
1953 #       foreach $e ( @entry ) {
1954 #           next unless $e =~ /([A-Z][A-Za-z0-9_]*)\.$HiSuffix$/o;
1955 #           next if $NoImplicitPrelude && $e =~ /Prelude\.$HiSuffix$/o;
1956 #
1957 #           $mod  = $1;
1958 #           $path = "$d/$e";
1959 #           $path =~ s,^\./,,;
1960 #
1961 #           if ( ! defined($HiMap{$mod}) ) {
1962 #               $HiMap{$mod} = $path;
1963 #           } elsif ( $mod ne 'Main' )  { # saves useless warnings...
1964 #               &already_mapped_err($mod, $HiMap{$mod}, $path);
1965 #           }
1966 #       }
1967 #       closedir(DIR); # || &tidy_up_and_die(1,"$Pgm: error when closing directory: $d\n");
1968     }
1969
1970 #
1971 # Not currently used:
1972 #
1973 #    $HiMapFile = "$Tmp_prefix.himap";
1974 #    unlink($HiMapFile);
1975 #    open(HIMAP, "> $HiMapFile") || &tidy_up_and_die(1,"$Pgm: can't open $HiMapFile\n");
1976 #    foreach $d (keys %HiMap) {
1977 #       print HIMAP $d, ' ', $HiMap{$d}, "\n";
1978 #    }
1979 #    close(HIMAP) || &tidy_up_and_die(1,"$Pgm: error when closing $HiMapFile\n");
1980
1981     $HiMapDone = 1;
1982 }
1983
1984 sub already_mapped_err {
1985     local($mod, $mapped_to, $path) = @_;
1986
1987     # OK, it isn't really an error if $mapped_to and $path turn
1988     # out to be the same thing.
1989     ($m_dev,$m_ino,$m_mode,$m_nlink,$m_uid,$m_gid,$m_rdev,$m_size,
1990      $m_atime,$m_mtime,$m_ctime,$m_blksize,$m_blocks) = stat($mapped_to);
1991     ($p_dev,$p_ino,$p_mode,$p_nlink,$p_uid,$p_gid,$p_rdev,$p_size,
1992      $p_atime,$p_mtime,$p_ctime,$p_blksize,$p_blocks) = stat($path);
1993
1994     return if $m_ino == $p_ino; # same inode number
1995
1996     print STDERR "$Pgm: module $mod already mapped to $mapped_to";
1997     print STDERR ";\n\tignoring: $path\n";
1998 }
1999 \end{code}
2000
2001 %************************************************************************
2002 %*                                                                      *
2003 \section[Driver-misc-utils]{Miscellaneous utilities}
2004 %*                                                                      *
2005 %************************************************************************
2006
2007 %************************************************************************
2008 %*                                                                      *
2009 \subsection[Driver-odir-ify]{@odir_ify@: Mangle filename if \tr{-odir} set}
2010 %*                                                                      *
2011 %************************************************************************
2012
2013 \begin{code}
2014 sub osuf_ify {
2015     local($ofile,$def_suffix) = @_;
2016
2017     return(($Osuffix eq '') ? "$ofile.$def_suffix" : "$ofile.$Osuffix" );
2018 }
2019
2020 sub odir_ify {
2021     local($orig_file, $def_suffix) = @_;
2022     if ($Specific_output_dir eq '') {   # do nothing
2023         &osuf_ify($orig_file, $def_suffix);
2024     } else {
2025         local ($orig_file_only);
2026         ($orig_file_only = $orig_file) =~ s|.*/||;
2027         &osuf_ify("$Specific_output_dir/$orig_file_only",$def_suffix);
2028     }
2029 }
2030 \end{code}
2031
2032 \begin{code}
2033 sub runGcc {
2034     local($is_hc_file, $hsc_out, $cc_as_o) = @_;
2035
2036     local($includes) = '-I' . join(' -I', @Include_dir);
2037     local($cc);
2038     local($s_output);
2039     local($c_flags) = "@CcBoth_flags";
2040     local($ddebug_flag) = ( $DEBUGging ) ? '-DDEBUG' : '';
2041
2042     # "input" files to use that are not in some weird directory;
2043     # to help C compilers grok .hc files [ToDo: de-hackify]
2044     local($cc_help)   = "ghc$$.c";
2045     local($cc_help_s) = "ghc$$.s";
2046
2047     $cc       = $CcRegd;
2048     $s_output = ($is_hc_file || $TargetPlatform =~ /^(hppa|i386)/) ? $cc_as_o : $cc_as;
2049     $c_flags .= " @CcRegd_flags";
2050     $c_flags .= ($is_hc_file) ? " @CcRegd_flags_hc"  : " @CcRegd_flags_c";
2051
2052     # C compiler won't like the .hc extension.  So we create
2053     # a tmp .c file which #include's the needful.
2054     open(TMP, "> $cc_help") || &tidy_up_and_die(1,"$Pgm: failed to open `$cc_help' (to write)\n");
2055     if ( $is_hc_file ) {
2056         print TMP <<EOINCL;
2057 #ifdef __STG_GCC_REGS__
2058 # if ! (defined(MAIN_REG_MAP) || defined(MARK_REG_MAP) || defined(SCAN_REG_MAP) || defined(SCAV_REG_MAP) || defined(FLUSH_REG_MAP))
2059 #  define MAIN_REG_MAP
2060 # endif
2061 #endif
2062 #include "stgdefs.h"
2063 EOINCL
2064         # user may have asked for #includes to be injected...
2065         print TMP @CcInjects if $#CcInjects >= 0;
2066     }
2067     # heave in the consistency info
2068     print TMP "static char ghc_cc_ID[] = \"\@(#)cc $ifile\t$Cc_major_version.$Cc_minor_version,$Cc_consist_options\";\n";
2069
2070     # and #include the real source
2071     print TMP "#include \"$hsc_out\"\n";
2072     close(TMP) || &tidy_up_and_die(1,"Failed writing to $cc_help\n");
2073
2074     local($to_do) = "$cc $Verbose $ddebug_flag $c_flags @Cpp_define -D__HASKELL1__=$Haskell1Version $includes $cc_help > $Tmp_prefix.ccout 2>&1 && ( if [ $cc_help_s != $s_output ] ; then mv $cc_help_s $s_output ; else exit 0 ; fi )";
2075     # note: __GLASGOW_HASKELL__ is pointedly *not* #defined at the C level.
2076     if ( $Only_preprocess_C ) { # HACK ALERT!
2077         $to_do =~ s/ -S\b//g;
2078     }
2079     @Files_to_tidy = ( $cc_help, $cc_help_s, $s_output );
2080     $PostprocessCcOutput = 1;   # hack, dear hack...
2081     &run_something($to_do, 'C compiler');
2082     $PostprocessCcOutput = 0;
2083     unlink($cc_help, $cc_help_s);
2084 }
2085 \end{code}
2086
2087 \begin{code}
2088 sub runMangler {
2089     local($is_hc_file, $cc_as_o, $cc_as, $ifile_root) = @_;
2090
2091     if ( $is_hc_file ) {
2092         # dynamically load assembler-fiddling code, which we are about to use:
2093         require('ghc-asm.prl')
2094         || &tidy_up_and_die(1,"$Pgm: panic: can't load ghc-asm.prl!\n");
2095     }
2096
2097     print STDERR `cat $cc_as_o` if $Dump_raw_asm; # to stderr, before mangling
2098
2099     if ($is_hc_file) {
2100         # post-process the assembler [.hc files only]
2101         &mangle_asm($cc_as_o, $cc_as);
2102
2103
2104 #OLD: for sanity:
2105 #OLD:   local($target) = 'oops';
2106 #OLD:   $target = '-alpha'      if $TargetPlatform =~ /^alpha-/;
2107 #OLD:   $target = '-hppa'       if $TargetPlatform =~ /^hppa/;
2108 #OLD:   $target = '-old-asm'    if $TargetPlatform =~ /^i386-/;
2109 #OLD:   $target = '-m68k'       if $TargetPlatform =~ /^m68k-/;
2110 #OLD:   $target = '-mips'       if $TargetPlatform =~ /^mips-/;
2111 #OLD:   $target = ''            if $TargetPlatform =~ /^powerpc-/;
2112 #OLD:   $target = '-solaris'    if $TargetPlatform =~ /^sparc-sun-solaris2/;
2113 #OLD:   $target = '-sparc'      if $TargetPlatform =~ /^sparc-sun-sunos4/;
2114 #OLD:
2115 #OLD:   if ( $target ne '' ) {
2116 #OLD:       require("ghc-asm$target.prl")
2117 #OLD:       || &tidy_up_and_die(1,"$Pgm: panic: can't load ghc-asm$target.prl!\n");
2118 #OLD:       &mangle_asm($cc_as_o, "$cc_as-2"); # the OLD one!
2119 #OLD:       &run_something("$Cmp -s $cc_as-2 $cc_as || $Diff $cc_as-2 $cc_as 1>&2 || exit 0",
2120 #OLD:           "Diff'ing old and new mangled .s files"); # NB: to stderr
2121 #OLD:   }
2122
2123     } elsif ($TargetPlatform =~ /^hppa/) {
2124         # minor mangling of non-threaded files for hp-pa only
2125         require('ghc-asm.prl')
2126         || &tidy_up_and_die(1,"$Pgm: panic: can't load ghc-asm-hppa.prl!\n");
2127         &mini_mangle_asm_hppa($cc_as_o, $cc_as);
2128
2129     } elsif ($TargetPlatform =~ /^i386/) {
2130         # extremely-minor OFFENSIVE mangling of non-threaded just one file
2131         require('ghc-asm.prl')
2132         || &tidy_up_and_die(1,"$Pgm: panic: can't load ghc-asm.prl!\n");
2133         &mini_mangle_asm_i386($cc_as_o, $cc_as);
2134     }
2135
2136     # save a copy of the .s file, even if we are carrying on...
2137     if ($do_as && $Keep_s_file_too) {
2138         local($to_do) = "$Rm $ifile_root.s; $Cp $cc_as $ifile_root.s";
2139         &run_something($to_do, 'Saving copy of .s file');
2140     }
2141 }
2142 \end{code}
2143
2144 \begin{code}
2145 sub runAs {
2146     local($as_out, $ifile_root) = @_;
2147
2148     local($asmblr) = ( $As ) ? $As : $CcRegd;
2149
2150     if ( ! $SplitObjFiles ) {
2151         local($to_do)  = "$asmblr -o $as_out -c @As_flags $cc_as";
2152         @Files_to_tidy = ( $as_out );
2153         &run_something($to_do, 'Unix assembler');
2154
2155     } else { # more complicated split-ification...
2156
2157         # must assemble files $Tmp_prefix__[1 .. $NoOfSplitFiles].s
2158
2159         # If -odir is used, great, just pin it in front of the
2160         # generated split file names. If it hasn't been set, we
2161         # snatch it from the ifile_root.
2162         #
2163         # 
2164
2165         if ( $Specific_output_dir eq '' ) {
2166             $Specific_output_dir = ${ifile_root};
2167         }
2168
2169         for ($f = 1; $f <= $NoOfSplitFiles; $f++ ) {
2170             local($split_out) = &odir_ify("${ifile_root}__${f}",'o');
2171             local($to_do) = "$asmblr -o $split_out -c @As_flags ${Tmp_prefix}__${f}.s";
2172             @Files_to_tidy = ( $split_out );
2173
2174             &run_something($to_do, 'Unix assembler');
2175         }
2176     }
2177 }
2178 \end{code}
2179
2180 %************************************************************************
2181 %*                                                                      *
2182 \subsection[Driver-run-something]{@run_something@: Run a phase}
2183 %*                                                                      *
2184 %************************************************************************
2185
2186 \begin{code}
2187 sub run_something {
2188     local($str_to_do, $tidy_name) = @_;
2189
2190     print STDERR "\n$tidy_name:\n\t" if $Verbose;
2191     print STDERR "$str_to_do\n" if $Verbose;
2192
2193     if ($Using_dump_file) {
2194         open(DUMP, ">> $Specific_dump_file")
2195             || &tidy_up_and_die(1,"$Pgm: failed to open `$Specific_dump_file'\n");
2196         print DUMP "\nCompilation Dump for: $str_to_do\n\n";
2197         close(DUMP) 
2198             || &tidy_up_and_die(1,"$Pgm: failed closing `$Specific_dump_file'\n");
2199     }
2200
2201     local($return_val) = 0;
2202     system("$Time $str_to_do");
2203     $return_val = $?;
2204
2205     if ( $PostprocessCcOutput ) { # hack, continued
2206         open(CCOUT, "< $Tmp_prefix.ccout")
2207             || &tidy_up_and_die(1,"$Pgm: failed to open `$Tmp_prefix.ccout'\n");
2208         while ( <CCOUT> ) {
2209             next if /attribute directive ignored/;
2210             next if /call-clobbered/;
2211             next if /from .*COptRegs\.lh/;
2212             next if /from .*(stg|rts)defs\.h:/;
2213             next if /from ghc\d+.c:\d+:/;
2214             next if /from .*\.lc/;
2215             next if /from .*SMinternal\.l?h/;
2216             next if /ANSI C does not support \`long long\'/;
2217             next if /warning:.*was declared \`extern\' and later \`static\'/;
2218             next if /warning: assignment discards \`const\' from pointer target type/;
2219             next if /: At top level:$/;
2220             next if /: In function \`.*\':$/;
2221             next if /\`ghc_cc_ID\' defined but not used/;
2222             print STDERR $_;
2223         }
2224         close(CCOUT) || &tidy_up_and_die(1,"$Pgm: failed closing `$Tmp_prefix.ccout'\n");
2225     }
2226
2227     if ($return_val != 0) {
2228         if ($Using_dump_file) {
2229             print STDERR "Compilation Errors dumped in $Specific_dump_file\n";
2230         }
2231
2232         &tidy_up_and_die($return_val, '');
2233     }
2234     $Using_dump_file = 0;
2235 }
2236 \end{code}
2237
2238 %************************************************************************
2239 %*                                                                      *
2240 \subsection[Driver-ghctiming]{Emit nofibbish GHC timings}
2241 %*                                                                      *
2242 %************************************************************************
2243
2244 NB: nearly the same as in @runstdtest@ script.
2245
2246 \begin{code}
2247 sub process_ghc_timings {
2248     local($StatsFile) = "$Tmp_prefix.stat";
2249     local($SysSpecificTiming) = 'ghc';
2250
2251     open(STATS, $StatsFile) || die "Failed when opening $StatsFile\n";
2252     local($tot_live) = 0; # for calculating avg residency
2253
2254     while (<STATS>) {
2255         $tot_live += $1 if /^\s*\d+\s+\d+\s+\d+\.\d+\%\s+(\d+)\s+\d+\.\d+\%/;
2256
2257         $BytesAlloc = $1 if /^\s*([0-9,]+) bytes allocated in the heap/;
2258
2259         if ( /^\s*([0-9,]+) bytes maximum residency .* (\d+) sample/ ) {
2260             $MaxResidency = $1; $ResidencySamples = $2;
2261         }
2262
2263         $GCs = $1 if /^\s*([0-9,]+) garbage collections? performed/;
2264
2265         if ( /^\s*INIT\s+time\s*(\d+\.\d\d)s\s*\(\s*(\d+\.\d\d)s elapsed\)/ ) {
2266             $InitTime = $1; $InitElapsed = $2;
2267         } elsif ( /^\s*MUT\s+time\s*(\d+\.\d\d)s\s*\(\s*(\d+\.\d\d)s elapsed\)/ ) {
2268             $MutTime = $1; $MutElapsed = $2;
2269         } elsif ( /^\s*GC\s+time\s*(\d+\.\d\d)s\s*\(\s*(\d+\.\d\d)s elapsed\)/ ) {
2270             $GcTime = $1; $GcElapsed = $2;
2271         }
2272     }
2273     close(STATS) || die "Failed when closing $StatsFile\n";
2274     if ( defined($ResidencySamples) && $ResidencySamples > 0 ) {
2275         $AvgResidency = int ($tot_live / $ResidencySamples) ;
2276     }
2277
2278     # warn about what we didn't find
2279     print STDERR "Warning: BytesAlloc not found in stats file\n" unless defined($BytesAlloc);
2280     print STDERR "Warning: GCs not found in stats file\n" unless defined($GCs);
2281     print STDERR "Warning: InitTime not found in stats file\n" unless defined($InitTime);
2282     print STDERR "Warning: InitElapsed not found in stats file\n" unless defined($InitElapsed);
2283     print STDERR "Warning: MutTime not found in stats file\n" unless defined($MutTime);
2284     print STDERR "Warning: MutElapsed not found in stats file\n" unless defined($MutElapsed);
2285     print STDERR "Warning: GcTime inot found in stats file\n" unless defined($GcTime);
2286     print STDERR "Warning: GcElapsed not found in stats file\n" unless defined($GcElapsed);
2287
2288     # things we didn't necessarily expect to find
2289     $MaxResidency     = 0 unless defined($MaxResidency);
2290     $AvgResidency     = 0 unless defined($AvgResidency);
2291     $ResidencySamples = 0 unless defined($ResidencySamples);
2292
2293     # a bit of tidying
2294     $BytesAlloc =~ s/,//g;
2295     $MaxResidency =~ s/,//g;
2296     $GCs =~ s/,//g;
2297     $InitTime =~ s/,//g;
2298     $InitElapsed =~ s/,//g;
2299     $MutTime =~ s/,//g;
2300     $MutElapsed =~ s/,//g;
2301     $GcTime =~ s/,//g;
2302     $GcElapsed =~ s/,//g;
2303
2304     # print out what we found
2305     print STDERR "<<$SysSpecificTiming: ",
2306         "$BytesAlloc bytes, $GCs GCs, $AvgResidency/$MaxResidency avg/max bytes residency ($ResidencySamples samples), $InitTime INIT ($InitElapsed elapsed), $MutTime MUT ($MutElapsed elapsed), $GcTime GC ($GcElapsed elapsed)",
2307         " :$SysSpecificTiming>>\n";
2308
2309     # OK, party over
2310     unlink $StatsFile;
2311 }
2312 \end{code}
2313
2314 %************************************************************************
2315 %*                                                                      *
2316 \subsection[Driver-dying]{@tidy_up@ and @tidy_up_and_die@: Dying gracefully}
2317 %*                                                                      *
2318 %************************************************************************
2319
2320 \begin{code}
2321 sub tidy_up {
2322     local($to_do) = "\n$Rm $Tmp_prefix*";
2323     if ( $Tmp_prefix !~ /^\s*$/ ) {
2324         print STDERR "$to_do\n" if $Verbose;
2325         system($to_do);
2326     }
2327 }
2328
2329 sub tidy_up_and_die {
2330     local($return_val, $msg) = @_;
2331
2332     # delete any files to tidy
2333     print STDERR "deleting... @Files_to_tidy\n" if $Verbose && $#Files_to_tidy >= 0;
2334     unlink @Files_to_tidy if $#Files_to_tidy >= 0;
2335
2336     &tidy_up();
2337     print STDERR $msg;
2338     exit (($return_val == 0) ? 0 : 1);
2339 }
2340 \end{code}
2341
2342 %************************************************************************
2343 %*                                                                      *
2344 \subsection[Driver-arg-with-arg]{@grab_arg_arg@: Do an argument with an argument}
2345 %*                                                                      *
2346 %************************************************************************
2347
2348 Some command-line arguments take an argument, e.g.,
2349 \tr{-Rmax-heapsize} expects a number to follow.  This can either be
2350 given a part of the same argument (\tr{-Rmax-heapsize8M}) or as the
2351 next argument (\tr{-Rmax-heapsize 8M}).  We allow both cases.
2352
2353 Note: no error-checking; \tr{-Rmax-heapsize -Rgc-stats} will silently
2354 gobble the second argument (and probably set the heapsize to something
2355 nonsensical).
2356 \begin{code}
2357 sub grab_arg_arg {
2358     local(*Args, $option, $rest_of_arg) = @_;
2359     
2360     if ($rest_of_arg) {
2361         return($rest_of_arg);
2362     } elsif ($#Args >= 0) {
2363         local($temp) = $Args[0]; shift(@Args); 
2364         return($temp);
2365     } else {
2366         print STDERR "$Pgm: no argument following $option option\n";
2367         $Status++;
2368     }
2369 }
2370 \end{code}
2371
2372 \begin{code}
2373 sub isntAntiFlag {
2374     local($flag) = @_;
2375     local($f);
2376
2377 #Not in HsC_antiflag ## NO!: and not already in HsC_flags
2378
2379     foreach $f ( @HsC_antiflags ) {
2380         return(0) if $flag eq $f;
2381     }
2382 #    foreach $f ( @HsC_flags ) {
2383 #       return(0) if $flag eq $f;
2384 #    }
2385     return(1);
2386 }
2387
2388 sub squashHscFlag {  # pretty terrible
2389     local($flag) = @_;
2390     local($f);
2391
2392     foreach $f ( @HsC_flags ) {
2393         if ($flag eq $f) { $f = ''; }
2394     }
2395 }
2396
2397 sub add_Hsc_flags {
2398     local(@flags) = @_;
2399     local($f);
2400
2401     foreach $f ( @flags ) {
2402         push( @HsC_flags, $f ) if &isntAntiFlag($f);
2403     }
2404 }
2405 \end{code}
2406
2407 Source files may have {-# OPTIONS ... #-} pragmas at the top, containing
2408 command line options we want to append to collection of commands specified
2409 directly. @check_for_source_options@ looks at the top of a de-lit'ified Haskell
2410 file for any such pragmas:
2411
2412 \begin{code}
2413 sub check_for_source_options {
2414     local($file) = @_;
2415
2416     open(FILE,$file) || return(1); # No big loss
2417
2418     while (<FILE>) {
2419         if ( /^{-# OPTIONS (.*)#-}/ ) {
2420            # add the options found at the back of the command line.
2421            local(@entries) = split(/\s+/,$1);
2422            push(@File_options, @entries);
2423         }
2424         elsif ( /^$/ ) { # ignore empty lines
2425            ;
2426         }
2427         else { # stop looking, something non-empty / not
2428                # {-# OPTIONS .. #-} encountered.
2429             break;
2430         }
2431     }
2432     close(FILE);
2433     return(0);
2434 }
2435 \end{code}
2436
2437
2438 We split the initial argv up into three arrays:
2439
2440   - @Cmd_opts 
2441   - @Link_file
2442   - @Input_file
2443
2444 the reason for doing so is to be able to deal
2445 with {-# OPTIONS #-} pragma in source files properly.
2446
2447 \begin{code}
2448 sub splitCmdLine {
2449     local(@args) = @_;
2450
2451 arg: while($_ = $args[0]) {
2452     shift(@args);
2453     # sigh, we have to deal with these -option arg specially here.
2454     /^-(tmpdir|odir|o|isuf|osuf|hisuf|hisuf-prelude|odump|syslib)$/ && 
2455        do { push(@Cmd_opts, $_); push(@Cmd_opts,$args[0]); shift(@args); next arg; };
2456     /^-./  && do { push(@Cmd_opts, $_); next arg; };
2457
2458     if (/\.[oa]$/) {
2459         push(@Link_file, $_);
2460     } else {
2461         push(@Input_file, $_);
2462     }
2463
2464     # input files must exist:
2465     if (! -f $_) {
2466         print STDERR "$Pgm: input file doesn't exist: $_\n";
2467         $Status++;
2468     }
2469   }
2470 }    
2471
2472 \end{code}
2473
2474 Command-line processor
2475
2476 \begin{code}
2477 sub processArgs {
2478     local(@Args) = @_;
2479
2480 # can't use getopt(s); what we want is too complicated
2481
2482 arg: while($_ = $Args[0]) {
2483     shift(@Args);
2484
2485     #---------- help -------------------------------------------------------
2486     if (/^-\?$/ || /^--?help$/) { print $LongUsage; exit $Status; }
2487
2488     #-----------version ----------------------------------------------------
2489     /^--version$/   && do { print STDERR "${PROJECTNAME}, version ${PROJECTVERSION}, patchlevel ${PROJECTPATCHLEVEL}\n"; exit $Status; };
2490
2491     #---------- verbosity and such -----------------------------------------
2492     /^-v$/          && do { $Verbose = '-v'; $Time = 'time'; next arg; };
2493
2494     #---------- what phases are to be run ----------------------------------
2495     /^-recomp/      && do { $Do_recomp_chkr = 1; next arg; };
2496
2497     /^-cpp$/        && do { $Cpp_flag_set = 1; next arg; };
2498     # change the global default:
2499     # we won't run cat; we'll run the real thing
2500         
2501     /^-C$/          && do { $Do_cc = 0; $Do_as = 0; $Do_lnkr = 0; $HscOut = '-C=';
2502                             next arg; };
2503     # stop after generating C
2504         
2505     /^-noC$/        && do { $HscOut = '-N='; $ProduceHi = '-nohifile=';
2506                             $Do_cc = 0; $Do_as = 0; $Do_lnkr = 0;
2507                             next arg; };
2508     # leave out actual C generation (debugging) [also turns off interface gen]
2509
2510     /^-hi$/         && do { $HiOnStdout = 1; $ProduceHi = '-hifile='; next arg; };
2511     # _do_ generate an interface; usually used as: -noC -hi
2512
2513     /^-nohi$/       && do { $ProduceHi = '-nohifile='; next arg; };
2514     # don't generate an interface (even if generating C)
2515
2516     /^-hi-diffs$/             && do { $HiDiff_flag = 'normal'; next arg; };
2517     /^-hi-diffs-with-usages$/ && do { $HiDiff_flag = 'usages'; next arg; };
2518     /^-no-hi-diffs$/          && do { $HiDiff_flag = '';       next arg; };
2519     # show/disable diffs if the interface file changes
2520
2521     /^-E$/          && do { push(@CcBoth_flags, '-E');
2522                             $Only_preprocess_C = 1;
2523                             $Do_as = 0; $Do_lnkr = 0; next arg; };
2524     # stop after preprocessing C
2525     /^-M$/          && do { $Only_generate_deps = 1; $Do_as = 0; $Do_lnkr = 0; next arg; };
2526     # only generate dependency information.
2527     /^-S$/          && do { $Do_as = 0; $Do_lnkr = 0; next arg; };
2528     # stop after generating assembler
2529         
2530     /^-c$/          && do { $Do_lnkr = 0; next arg; };
2531     # stop after generating .o files
2532
2533     /^-link-chk$/    && do { $LinkChk = 1; next arg; };
2534     /^-no-link-chk$/ && do { $LinkChk = 0; next arg; };
2535     # don't do consistency-checking after a link
2536
2537     /^-tmpdir$/ && do { $Tmp_prefix = &grab_arg_arg(*Args,'-tmpdir', '');
2538                         $Tmp_prefix = "$Tmp_prefix/ghc$$";
2539                         $ENV{'TMPDIR'} = $Tmp_prefix; # for those who use it...
2540                         next arg; };
2541     # use an alternate directory for temp files
2542
2543     #---------- redirect output --------------------------------------------
2544
2545     # -o <file>; applies to the last phase, whatever it is
2546     # "-o -" sends it to stdout
2547     # if <file> has a directory component, that dir must already exist
2548
2549     /^-odir$/       && do { $Specific_output_dir = &grab_arg_arg(*Args,'-odir', '');
2550                             #
2551                             # Hack, of the worst sort: don't do validation of
2552                             # odir argument if you're using -M (dependency generation).
2553                             #
2554                             if ( ! $Only_generate_deps && ! -d $Specific_output_dir) {
2555                                 print STDERR "$Pgm: -odir: no such directory: $Specific_output_dir\n";
2556                                 $Status++;
2557                             }
2558                             next arg; };
2559
2560     /^-o$/          && do { $Specific_output_file = &grab_arg_arg(*Args,'-o', '');
2561                             if ($Specific_output_file ne '-'
2562                              && $Specific_output_file =~ /(.*)\/[^\/]*$/) {
2563                                 local($dir_part) = $1;
2564                                 if (! -d $dir_part) {
2565                                     print STDERR "$Pgm: no such directory: $dir_part\n";
2566                                     $Status++;
2567                                 }
2568                             }
2569                             next arg; };
2570
2571     # NB: -isuf not documented yet (because it doesn't work yet)
2572     /^-isuf$/       && do { $Isuffix  = &grab_arg_arg(*Args,'-isuf', '');
2573                             if ($Isuffix =~ /\./ ) {
2574                                 print STDERR "$Pgm: -isuf suffix shouldn't contain a .\n";
2575                                 $Status++;
2576                             }
2577                             next arg; };
2578
2579     /^-osuf$/       && do { $Osuffix  = &grab_arg_arg(*Args,'-osuf', '');
2580                             if ($Osuffix =~ /\./ ) {
2581                                 print STDERR "$Pgm: -osuf suffix shouldn't contain a .\n";
2582                                 $Status++;
2583                             }
2584                             next arg; };
2585
2586     # -ohi <file>; send the interface to <file>; "-ohi -" to send to stdout
2587     /^-ohi$/        && do { $Specific_hi_file = &grab_arg_arg(*Args,'-ohi', '');
2588                             if ($Specific_hi_file ne '-'
2589                              && $Specific_hi_file =~ /(.*)\/[^\/]*$/) {
2590                                 local($dir_part) = $1;
2591                                 if (! -d $dir_part) {
2592                                     print STDERR "$Pgm: no such directory: $dir_part\n";
2593                                     $Status++;
2594                                 }
2595                             }
2596                             next arg; };
2597
2598     # The suffix to use when looking for interface files
2599     /^-hisuf$/      && do { $HiSuffix = &grab_arg_arg(*Args,'-hisuf', '');
2600                             if ($HiSuffix =~ /\./ ) {
2601                                 print STDERR "$Pgm: -hisuf suffix shouldn't contain a .\n";
2602                                 $Status++;
2603                             }
2604                             next arg; };
2605     # ToDo: remove, not a `normal' user thing to do (should be automatic)
2606     /^-hisuf-prelude$/      && do { $HiSuffix_prelude = &grab_arg_arg(*Args,'-hisuf-prelude', '');
2607                             if ($HiSuffix =~ /\./ ) {
2608                                 print STDERR "$Pgm: -hisuf-prelude suffix shouldn't contain a .\n";
2609                                 $Status++;
2610                             }
2611                             next arg; };
2612     /^-odump$/      && do { $Specific_dump_file = &grab_arg_arg(*Args,'-odump', '');
2613                             if ($Specific_dump_file =~ /(.*)\/[^\/]*$/) {
2614                                 local($dir_part) = $1;
2615                                 if (! -d $dir_part) {
2616                                     print STDERR "$Pgm: no such directory: $dir_part\n";
2617                                     $Status++;
2618                                 }
2619                             }
2620                             next arg; };
2621
2622     #-------------- scc & Profiling Stuff ----------------------------------
2623
2624     /^-prof$/ && do { $PROFing = 'p'; next arg; }; # profiling -- details later!
2625
2626     /^-auto/ && do {
2627                 # generate auto SCCs on top level bindings
2628                 # -auto-all = all top level bindings
2629                 # -auto     = only top level exported bindings
2630                 $PROFauto = ( /-all/ )
2631                             ? '-fauto-sccs-on-all-toplevs'
2632                             : '-fauto-sccs-on-exported-toplevs';
2633                 next arg; };
2634
2635     /^-caf-all/ && do { # generate individual CAF SCC annotations
2636                 $PROFcaf = '-fauto-sccs-on-individual-cafs';
2637                 next arg; };
2638
2639     /^-ignore-scc$/ && do {
2640                 # forces ignore of scc annotations even if profiling
2641                 $PROFignore_scc = '-W';
2642                 next arg; };
2643
2644     /^-G(.*)$/  && do { push(@HsC_flags, "-G=$1");   # set group for cost centres
2645                         next arg; };
2646
2647     /^-unprof-scc-auto/ && do {
2648                 # generate auto SCCs on top level bindings when not profiling.
2649                 # Used to measure optimisation effects of presence of sccs.
2650                 $UNPROFscc_auto = ( /-all/ )
2651                             ? '-fauto-sccs-on-all-toplevs'
2652                             : '-fauto-sccs-on-exported-toplevs';
2653                 next arg; };
2654
2655     #--------- ticky/concurrent/parallel -----------------------------------
2656     # we sort out the details a bit later on
2657
2658     /^-concurrent$/ && do { $CONCURing = 'c'; next arg; }; # concurrent Haskell
2659     /^-gransim$/    && do { $GRANing   = 'g'; next arg; }; # GranSim
2660     /^-ticky$/      && do { $TICKYing  = 't'; next arg; }; # ticky-ticky
2661     /^-parallel$/   && do { $PARing    = 'p'; next arg; }; # parallel Haskell
2662
2663     #-------------- "user ways" --------------------------------------------
2664
2665     (/^-user-setup-([a-oA-Z])$/ ) && 
2666            do {
2667                 /^-user-setup-([a-oA-Z])$/  && do { $BuildTag = "_$1"; };
2668
2669                 local($stuff) = $UserSetupOpts{$BuildTag};
2670                 local(@opts)  = split(/\s+/, $stuff);
2671                 
2672                 # feed relevant ops into the arg-processing loop (if any)
2673                 unshift(@Args, @opts) if $#opts >= 0;
2674
2675                 next arg; };
2676
2677     #---------- set search paths for libraries and things ------------------
2678
2679     # we do -i just like HBC (-i clears the list; -i<colon-separated-items>
2680     # prepends the items to the list); -I is for including C .h files.
2681
2682     /^-i$/          && do { @Import_dir = ();  # import path cleared!
2683                             @SysImport_dir = ();
2684                             print STDERR "WARNING: import paths cleared by `-i'\n";
2685                             next arg; };
2686
2687     /^-i(.*)/       && do { local(@new_items)
2688                               = split( /:/, &grab_arg_arg(*Args,'-i', $1));
2689                             unshift(@Import_dir, @new_items);
2690                             next arg; };
2691
2692     /^-I(.*)/       && do { push(@Include_dir,     &grab_arg_arg(*Args,'-I', $1)); next arg; };
2693     /^-L(.*)/       && do { push(@UserLibrary_dir, &grab_arg_arg(*Args,'-L', $1)); next arg; };
2694     /^-l(.*)/       && do { push(@UserLibrary,'-l'.&grab_arg_arg(*Args,'-l', $1)); next arg; };
2695
2696     /^-syslib(.*)/  && do { local($syslib) = &grab_arg_arg(*Args,'-syslib',$1);
2697                             print STDERR "$Pgm: no such system library (-syslib): $syslib\n",
2698                               $Status++ unless $syslib =~ /^(hbc|ghc|posix|contrib)$/;
2699
2700                             unshift(@SysImport_dir,
2701                                 ${INSTALLING}
2702                                 ? "$InstSysLibDir/$syslib/imports"
2703                                 : "$TopPwd/hslibs/$syslib/src");
2704
2705                             if ( ${INSTALLING} ) {
2706                                 push(@SysLibrary_dir,
2707                                         ("$InstSysLibDir"));
2708                             } else {
2709                                 push(@SysLibrary_dir,
2710                                         ("$TopPwd/hslibs/$syslib"
2711                                         ,"$TopPwd/hslibs/$syslib/cbits"));
2712                             }
2713
2714                             push(@SysLibrary, "-lHS$syslib");
2715                             push(@SysLibrary, "-lHS${syslib}_cbits")
2716                               unless $syslib eq 'contrib'; #HACK! it has no cbits
2717
2718                             next arg; };
2719
2720     #=======================================================================
2721     # various flags that we can harmlessly send to one program or another
2722     # (we will later "reclaim" some of the compiler ones now sent to gcc)
2723     #=======================================================================
2724
2725     #---------- this driver itself (ghc) -----------------------------------
2726     # these change what executable is run for each phase:
2727     /^-pgmL(.*)$/   && do { $Unlit      = $1; next arg; };
2728     /^-pgmP(.*)$/   && do { $HsCpp      = $1; next arg; };
2729     /^-pgmC(.*)$/   && do { $HsC        = $1; next arg; };
2730     /^-pgmcO?(.*)$/ && do { $CcRegd     = $1; next arg; }; # the O? for back compat
2731     /^-pgma(.*)$/   && do { $As         = $1; next arg; };
2732     /^-pgml(.*)$/   && do { $Lnkr       = $1; next arg; };
2733     /^-pgmdep(.*)$/ && do { $MkDependHS = $1; next arg; };
2734
2735     #---------- the get-anything-through opts (all pgms) -------------------
2736     # these allow arbitrary option-strings to go to any phase:
2737     /^-optL(.*)$/   && do { push(@Unlit_flags,      $1); next arg; };
2738     /^-optP(.*)$/   && do { push(@HsCpp_flags,      $1); next arg; };
2739     /^-optCrts(.*)$/&& do { push(@HsC_rts_flags,    $1); next arg; };
2740     /^-optC(.*)$/   && do { push(@HsC_flags,        $1); next arg; };
2741     /^-optcpp(.*)$/ && do { push(@Cpp_define,       $1); next arg; };
2742     /^-optc(.*)$/   && do { push(@CcBoth_flags,     $1); next arg; };
2743     /^-opta(.*)$/   && do { push(@As_flags,         $1); next arg; };
2744     /^-optl(.*)$/   && do { push(@Ld_flags,         $1); next arg; };
2745     /^-optdep(.*)$/ && do { push(@MkDependHS_flags, $1); next arg; };
2746
2747     #---------- Haskell C pre-processor (hscpp) ----------------------------
2748     /^-D(.*)/       && do { push(@HsCpp_flags, "'-D".&grab_arg_arg(*Args,'-D',$1)."'"); next arg; };
2749     /^-U(.*)/       && do { push(@HsCpp_flags, "'-U".&grab_arg_arg(*Args,'-U',$1)."'"); next arg; };
2750
2751     /^-genSPECS/   && do { $Cpp_flag_set = 1;
2752                            $genSPECS_flag = $_;
2753                             next arg; };
2754
2755     #---------- post-Haskell "assembler"------------------------------------
2756     /^-ddump-raw-asm$/            && do { $Dump_raw_asm        = 1; next arg; };
2757     /^-ddump-asm-splitting-info$/ && do { $Dump_asm_splitting_info = 1; next arg; };
2758
2759     #---------- Haskell compiler (hsc) -------------------------------------
2760
2761     /^-keep-hc-files?-too$/     && do { $Keep_hc_file_too = 1; next arg; };
2762     /^-keep-s-files?-too$/      && do { $Keep_s_file_too = 1;  next arg; };
2763
2764     /^-fhaskell-1\.3$/          && do { next arg; }; # a no-op right now
2765
2766     /^-fignore-interface-pragmas$/ && do { push(@HsC_flags, $_); next arg; };
2767
2768     /^-fno-implicit-prelude$/      && do { $NoImplicitPrelude= 1; push(@HsC_flags, $_); next arg; };
2769      # don't do stack checking using page fault `trick'.
2770      # (esoteric).
2771     /^-fstack-check$/              && do { $StkChkByPageFaultOK = 0; next arg; };
2772      #
2773      # have the compiler proper generate concurrent code,
2774      # really only used when you want to configure your own
2775      # special user compilation way. (Use -concurrent when
2776      # compiling `Concurrent Haskell' programs).
2777      #
2778      # (ditto for -fgransim, fscc-profiling and -fticky-ticky)
2779      #
2780     /^-fconcurrent$/      && do { push(@HsC_flags,$_); next arg; };
2781     /^-fscc-profiling$/   && do { push(@HsC_flags,$_); next arg; };
2782     /^-fticky-ticky$/     && do { push(@HsC_flags,$_); next arg; };
2783     /^-fgransim$/         && do { push(@HsC_flags,$_); next arg; };
2784
2785     /^-user-prelude-force/      && do { # ignore if not -user-prelude
2786                                         next arg; };
2787
2788     /^-split-objs/      && do {
2789                         if ( $TargetPlatform !~ /^(alpha|hppa1\.1|i386|m68k|mips|powerpc|sparc)-/ ) {
2790                             $SplitObjFiles = 0;
2791                             print STDERR "WARNING: don't know how to split objects on this platform: $TargetPlatform\n`-split-objs' option ignored\n";
2792                         } else {
2793                             $SplitObjFiles = 1;
2794                             $HscOut = '-C=';
2795
2796                             push(@HsC_flags, "-fglobalise-toplev-names"); 
2797                             push(@CcBoth_flags, '-DUSE_SPLIT_MARKERS');
2798
2799                             require('ghc-split.prl')
2800                              || &tidy_up_and_die(1,"$Pgm: panic: can't load ghc-split.prl!\n");
2801                         }
2802                         next arg; };
2803
2804     /^-fglasgow-exts$/
2805                 && do { push(@HsC_flags, $_);
2806                         push(@HsP_flags, '-N');
2807
2808 #                       push(@HsC_flags, '-fshow-import-specs');
2809
2810                         next arg; };
2811
2812     /^-fspeciali[sz]e-unboxed$/
2813                 && do { $Oopt_DoSpecialise      = '-fspecialise';
2814                         $Oopt_SpecialiseUnboxed = '-fspecialise-unboxed';
2815                         next arg; };
2816     /^-fspeciali[sz]e$/
2817                 && do { $Oopt_DoSpecialise = '-fspecialise'; next arg; };
2818     /^-fno-speciali[sz]e$/
2819                 && do { $Oopt_DoSpecialise = ''; next arg; };
2820
2821
2822 # Now the foldr/build options, which are *on* by default (for -O).
2823
2824     /^-ffoldr-build$/
2825                     && do { $Oopt_FoldrBuild = 1; 
2826                             $Oopt_FB_Support = '-fdo-arity-expand';
2827                             #print "Yes F/B\n";
2828                             next arg; };
2829
2830     /^-fno-foldr-build$/
2831                     && do { $Oopt_FoldrBuild = 0; 
2832                             $Oopt_FB_Support = ''; 
2833                             next arg; };
2834
2835     /^-fno-foldr-build-rule$/
2836                     && do { $Oopt_FoldrBuild = 0; 
2837                             next arg; };
2838
2839     /^-fno-enable-tech$/
2840                     && do { $Oopt_FB_Support = ''; 
2841                             next arg; };
2842
2843     /^-fno-snapback-to-append$/
2844                     && do { $Oopt_FoldrBuildInline .= ' -fdo-not-fold-back-append '; 
2845                             next arg; };
2846
2847     # ---------------
2848
2849     /^-fasm-(.*)$/  && do { $HscOut = '-S='; next arg; }; # force using nativeGen
2850     /^-fvia-C$/     && do { $HscOut = '-C='; next arg; }; # force using C compiler
2851
2852     # ---------------
2853
2854     /^(-funfolding-use-threshold)(.*)$/
2855                     && do { $Oopt_UnfoldingUseThreshold = $1 . &grab_arg_arg(*Args,$1, $2);
2856                             next arg; };
2857
2858     /^(-fmax-simplifier-iterations)(.*)$/
2859                     && do { $Oopt_MaxSimplifierIterations = $1 . &grab_arg_arg(*Args,$1, $2);
2860                             next arg; };
2861
2862     /^-fno-pedantic-bottoms$/
2863                     && do { $Oopt_PedanticBottoms = ''; next arg; };
2864
2865     /^-fdo-monad-eta-expansion$/
2866                     && do { $Oopt_MonadEtaExpansion = $_; next arg; };
2867
2868     /^-fno-let-from-(case|app|strict-let)$/ # experimental, really (WDP 95/10)
2869                     && do { push(@HsC_flags, $_); next arg; };
2870
2871     /^(-freturn-in-regs-threshold)(.*)$/
2872                     && do { local($what) = $1;
2873                             local($num)  = &grab_arg_arg(*Args,$what, $2);
2874                             if ($num < 2 || $num > 8) {
2875                                 die "Bad experimental flag: $_\n";
2876                             } else {
2877                                 $HscOut = '-C='; # force using C compiler
2878                                 push(@HsC_flags, "$what$num");
2879                                 push(@CcRegd_flags, "-D__STG_REGS_AVAIL__=$num");
2880                             }
2881                             next arg; };
2882
2883     # --------------- Warnings etc. ------
2884
2885     /^-f(show-import-specs)/
2886                     && do { push(@HsC_flags, $_); next arg; };
2887
2888     # for now, just -fwarn-name-shadowing
2889     /^-fwarn-(.*)$/   && do { push(@HsC_flags, $_); next arg; };
2890     /^-fno-(.*)$/   && do { push(@HsC_antiflags, "-f$1");
2891                             &squashHscFlag("-f$1");
2892                             next arg; };
2893
2894     # --------------- platform specific flags (for gcc mostly) ----------------
2895
2896     /^-mlong-calls$/ && do { # for GCC for HP-PA boxes,
2897                              # for 2.6.x..?, does not apply for 2.7.2
2898                              # any longer.
2899                             unshift(@CcBoth_flags, ( $_ ));
2900                             next arg; };
2901
2902     /^-m(v8|sparclite|cypress|supersparc|cpu=(cypress|supersparc))$/
2903                      && do { # for GCC for SPARCs
2904                             unshift(@CcBoth_flags, ( $_ ));
2905                             next arg; };
2906
2907     /^-monly-([432])-regs/ && do { # for iX86 boxes only; no effect otherwise
2908                             $StolenX86Regs = $1;
2909                             next arg; };
2910
2911     #*************** ... and lots of debugging ones (form: -d* )
2912
2913     # -d(no-)core-lint is done this way so it is turn-off-able.
2914     /^-dcore-lint/       && do { $CoreLint = '-dcore-lint'; next arg; };
2915     /^-dno-core-lint/    && do { $CoreLint = '';            next arg; };
2916     # Ditto for STG lint
2917     /^-dstg-lint/       && do { $StgLint = '-dstg-lint'; next arg; };
2918     /^-dno-stg-lint/    && do { $StgLint = '';           next arg; };
2919
2920     /^-d(dump|ppr)-/         && do { push(@HsC_flags, $_); next arg; };
2921     /^-dverbose-(simpl|stg)/ && do { push(@HsC_flags, $_); next arg; };
2922     /^-dshow-passes/         && do { push(@HsC_flags, $_); next arg; };
2923     /^-dshow-rn-trace/       && do { push(@HsC_flags, $_); next arg; };
2924     /^-dsource-stats/        && do { push(@HsC_flags, $_); next arg; };
2925     /^-dsimplifier-stats/    && do { push(@HsC_flags, $_); next arg; };
2926     /^-dstg-stats/           && do { $Oopt_StgStats = $_; next arg; };
2927
2928     #*************** ... and now all these -R* ones for its runtime system...
2929
2930     /^-Rscale-sizes?(.*)/ && do {
2931         $Scale_sizes_by = &grab_arg_arg(*Args,'-Rscale-sizes', $1);
2932         next arg; };
2933
2934     /^(-H|-Rmax-heapsize)(.*)/ && do {
2935         local($heap_size) = &grab_arg_arg(*Args,$1, $2);
2936         if ($heap_size =~ /(\d+)[Kk]$/) {
2937             $heap_size = $1 * 1000;
2938         } elsif ($heap_size =~ /(\d+)[Mm]$/) {
2939             $heap_size = $1 * 1000 * 1000;
2940         } elsif ($heap_size =~ /(\d+)[Gg]$/) {
2941             $heap_size = $1 * 1000 * 1000 * 1000;
2942         }
2943         if ($heap_size <= 0) {
2944             print STDERR "$Pgm: resetting heap-size to zero!!! $heap_size\n";
2945             $Specific_heap_size = 0;
2946         
2947         # if several heap sizes given, take the largest...
2948         } elsif ($heap_size >= $Specific_heap_size) {
2949             $Specific_heap_size = $heap_size;
2950         } else {
2951             print STDERR "$Pgm: ignoring heap-size-setting option ($_)...not the largest seen\n";
2952         }
2953         next arg; };
2954
2955     /^-(K|Rmax-(stk|stack)size)(.*)/ && do {
2956         local($flag) = $1;
2957         local($stk_size) = &grab_arg_arg(*Args,'-Rmax-stksize', $3);
2958         if ($stk_size =~ /(\d+)[Kk]$/) {
2959             $stk_size = $1 * 1000;
2960         } elsif ($stk_size =~ /(\d+)[Mm]$/) {
2961             $stk_size = $1 * 1000 * 1000;
2962         } elsif ($stk_size =~ /(\d+)[Gg]$/) {
2963             $stk_size = $1 * 1000 * 1000 * 1000;
2964         }
2965         if ($stk_size <= 0) {
2966             print STDERR "$Pgm: resetting stack-size to zero!!! $stk_size\n";
2967             $Specific_stk_size = 0;
2968
2969         # if several stack sizes given, take the largest...
2970         } elsif ($stk_size >= $Specific_stk_size) {
2971             $Specific_stk_size = $stk_size;
2972         } else {
2973             print STDERR "$Pgm: ignoring stack-size-setting option ($flag $stk_size)...not the largest seen\n";
2974         }
2975         next arg; };
2976
2977     /^-Rgc-stats$/ && do {  $CollectingGCstats++;
2978                             # the two RTSs do this diff ways; we will try to compensate
2979                             next arg; };
2980
2981     /^-Rghc-timing/ && do { $CollectGhcTimings = 1; next arg; };
2982
2983     #---------- C high-level assembler (gcc) -------------------------------
2984     /^-(Wall|ansi|pedantic)$/ && do { push(@CcBoth_flags, $_); next arg; };
2985
2986     # -dgcc-lint is a useful way of making GCC very fussy.
2987     # From alan@spri.levels.unisa.edu.au (Alan Modra).
2988     /^-dgcc-lint$/ && do { push(@CcBoth_flags, '-Wall -Wpointer-arith -Wbad-function-cast -Wcast-qual -Wstrict-prototypes -Wmissing-prototypes -Wmissing-declarations -Wnested-externs'); next arg; };
2989     # An alternate set, from mark@sgcs.com (Mark W. Snitily)
2990     # -Wall -Wstrict-prototypes -Wmissing-prototypes -Wcast-align -Wshadow
2991
2992     # inject "#include <wurble>" into the compiler's C output!
2993
2994     /^-#include(.*)/    && do {
2995         local($to_include) = &grab_arg_arg(*Args,'-#include', $1);
2996         push(@CcInjects, "#include $to_include\n");
2997         next arg; };
2998
2999     #---------- Linker (gcc, really) ---------------------------------------
3000
3001     /^-static$/         && do { push(@Ld_flags, $_); next arg; };
3002
3003     #---------- mixed cc and linker magic ----------------------------------
3004     # this optimisation stuff is finally sorted out later on...
3005
3006     /^-O2-for-C$/ && do { $MinusO2ForC = 1; next arg; };
3007
3008     /^-O[1-2]?$/ && do {
3009                 local($opt_lev) = ( /^-O2$/ ) ? 2 : 1; # max 'em
3010                 $OptLevel = ( $opt_lev > $OptLevel ) ? $opt_lev : $OptLevel;
3011
3012                 $HscOut = '-C=' if $OptLevel == 2; # force use of C compiler
3013                 next arg; };
3014
3015     /^-Onot$/   && do { $OptLevel = 0; next arg; }; # # set it to <no opt>
3016
3017     /^-Ofile(.*)/ && do {
3018                 $OptLevel = 3;
3019                 local($ofile) = &grab_arg_arg(*Args,'-Ofile', $1);
3020                 @HsC_minusO3_flags = ();
3021
3022                 open(OFILE, "< $ofile") || die "Can't open $ofile!\n";
3023                 while (<OFILE>) {
3024                     chop;
3025                     s/\#.*//;       # death to comments
3026                     s/[ \t]+//g;    # death to whitespace
3027                     next if /^$/;   # ditto, blank lines
3028                     s/([()*{}])/\\$1/g;    # protect shell metacharacters
3029                     if ( /^C:(.*)/ ) {
3030                         push(@CcBoth_flags, $1);
3031                     } else {
3032                         push(@HsC_minusO3_flags, $_);
3033                     }
3034                 }
3035                 close(OFILE);
3036                 next arg; };
3037
3038     /^-debug$/  && do { # all this does is mark a .hc/.o as "debugging"
3039                         # in the consistency info
3040                         $DEBUGging = 'd';
3041                         next arg; };
3042
3043     #---------- linking .a file --------------------------------------------
3044
3045     /^-Main(.*)/ && do {
3046                 # specifies main or mainPrimIO to be linked
3047                 $Ld_main = $1;
3048                 next arg; }; 
3049
3050     #---------- catch unrecognized flags -----------------------------------
3051
3052     /^-./ && do {
3053         print STDERR "$Pgm: unrecognised option: $_\n";
3054         $Status++;
3055         next arg; };
3056
3057 }
3058
3059 } # end of processArgs
3060
3061 \end{code}