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