diff options
Diffstat (limited to 'ghc/driver/ghc.lprl')
-rw-r--r-- | ghc/driver/ghc.lprl | 1471 |
1 files changed, 685 insertions, 786 deletions
diff --git a/ghc/driver/ghc.lprl b/ghc/driver/ghc.lprl index 8ccef55cfc..09f1bef6e4 100644 --- a/ghc/driver/ghc.lprl +++ b/ghc/driver/ghc.lprl @@ -37,7 +37,7 @@ possible phases of a compilation: For each input file, the phase to START with is determined by the file's suffix: - .lhs literate Haskell: lit2pgm - - .hs illiterate Haskell: hsp + - .hs illiterate Haskell: hsc - .hc C from the Haskell compiler: gcc - .c C not from the Haskell compiler: gcc - .s assembly language: as @@ -56,7 +56,7 @@ option: Other commonly-used options are: - -O An `optimising' package of options, to produce faster code + -O An `optimising' package of compiler flags, for faster code -prof Compile for cost-centre profiling (add -auto for automagic cost-centres on top-level functions) @@ -108,17 +108,19 @@ if (! $ENV{'GLASGOW_HASKELL_ROOT'}) { # good -- death to environment variables $TopPwd = '$(TOP_PWD)'; $InstLibDirGhc = '$(INSTLIBDIR_GHC)'; $InstDataDirGhc = '$(INSTDATADIR_GHC)'; +# $InstSysLibDir = '$(INSTLIBDIR_HSLIBS)'; ToDo ToDo + $InstSysLibDir = '$(TOP_PWD)/hslibs'; } else { $TopPwd = $ENV{'GLASGOW_HASKELL_ROOT'}; - if ( '$(INSTLIBDIR_GHC)' =~ /^\/(local\/fp|usr\/local)(\/.*)/ ) { - $InstLibDirGhc = $ENV{'GLASGOW_HASKELL_ROOT'} . $2; + if ('$(INSTLIBDIR_GHC)' =~ /.*(\/lib\/ghc\/\d\.\d\d\/[^-]-[^-]-[^-]\/.*)/) { + $InstLibDirGhc = $ENV{'GLASGOW_HASKELL_ROOT'} . $1; } else { print STDERR "GLASGOW_HASKELL_ROOT environment variable is set;\nBut can't untangle $(INSTLIBDIR_GHC).\n(Installation error)\n"; exit(1); } - if ( '$(INSTDATADIR_GHC)' =~ /\/(local\/fp|usr\/local)(\/.*)/ ) { + if ('$(INSTDATADIR_GHC)' =~ /.*(\/lib\/ghc\/\d\.\d\d\/.*)/) { $InstDataDirGhc = $ENV{'GLASGOW_HASKELL_ROOT'} . $2; } else { print STDERR "GLASGOW_HASKELL_ROOT environment variable is set;\nBut can't untangle $(INSTDATADIR_GHC).\n(Installation error)\n"; @@ -128,8 +130,6 @@ if (! $ENV{'GLASGOW_HASKELL_ROOT'}) { # good -- death to environment variables $Status = 0; # just used for exit() status $Verbose = ''; -$CoreLint = ''; -$Time = ''; # ToDo: mkworld-ize the timing command # set up signal handler sub quit_upon_signal { &tidy_up_and_die(1, ''); } @@ -138,7 +138,7 @@ $SIG{'QUIT'} = 'quit_upon_signal'; # where to get "require"d .prl files at runtime (poor man's dynamic loading) # (use LIB, not DATA, because we can't be sure of arch-independence) -@INC = ( ( $(INSTALLING) ) ? "$InstLibDirGhc" +@INC = ( ( $(INSTALLING) ) ? $InstLibDirGhc : "$TopPwd/$(CURRENT_DIR)" ); if ( $ENV{'TMPDIR'} ) { # where to make tmp file names @@ -154,7 +154,12 @@ $Unlit = ( $(INSTALLING) ) ? "$InstLibDirGhc/unlit" : "$TopPwd/$(CURRENT_DIR)/$(GHC_UNLIT)"; @Unlit_flags = (); -$Cat = "cat"; +$Cp = '$(CP)'; +$Rm = '$(RM)'; +$Diff = '$(CONTEXT_DIFF)'; +$Cat = 'cat'; +$Cmp = 'cmp'; +$Time = ''; $HsCpp = # but this is re-set to "cat" (after options) if -cpp not seen ( $(INSTALLING) ) ? "$InstLibDirGhc/hscpp" @@ -162,10 +167,6 @@ $HsCpp = # but this is re-set to "cat" (after options) if -cpp not seen @HsCpp_flags = (); $genSPECS_flag = ''; # See ../utils/hscpp/hscpp.prl -$HsP = ( $(INSTALLING) ) ? "$InstLibDirGhc/hsp" - : "$TopPwd/$(CURRENT_DIR)/$(GHC_HSP)"; -@HsP_flags = (); - $HsC = ( $(INSTALLING) ) ? "$InstLibDirGhc/hsc" : "$TopPwd/$(CURRENT_DIR)/$(GHC_HSC)"; @@ -177,10 +178,11 @@ $SysMan = ( $(INSTALLING) ) ? "$InstLibDirGhc/SysMan" # terrible things to cache behavior. $Specific_heap_size = 6 * 1000 * 1000; $Specific_stk_size = 1000 * 1000; -$Scale_sizes_by = 1.0; -$RTS_style = $(GHC_RTS_STYLE); -@HsC_rts_flags = (); +$Scale_sizes_by = 1.0; +@HsC_rts_flags = (); +@HsP_flags = (); # these are the flags destined solely for + # the flex/yacc parser @HsC_flags = (); @HsC_antiflags = (); \end{code} @@ -189,9 +191,10 @@ The optimisations/etc to be done by the compiler are {\em normally} expressed with a \tr{-O} (or \tr{-O2}) flag, or by its absence. \begin{code} -$OptLevel = 0; # no -O == 0; -O == 1; -O2 == 2; -Ofile == 3 -$MinusO2ForC = 0; # set to 1 if -O2 should be given to C compiler +$OptLevel = 0; # no -O == 0; -O == 1; -O2 == 2; -Ofile == 3 +$MinusO2ForC = 0; # set to 1 if -O2 should be given to C compiler $StolenX86Regs = 4; # **HACK*** of the very worst sort +$CoreLint = ''; \end{code} These variables represent parts of the -O/-O2/etc ``templates,'' @@ -202,41 +205,31 @@ $Oopt_UnfoldingUseThreshold = '-fsimpl-uf-use-threshold3'; $Oopt_MaxSimplifierIterations = '-fmax-simplifier-iterations4'; $Oopt_PedanticBottoms = '-fpedantic-bottoms'; # ON by default $Oopt_MonadEtaExpansion = ''; -#OLD:$Oopt_LambdaLift = ''; -$Oopt_AddAutoSccs = ''; $Oopt_FinalStgProfilingMassage = ''; $Oopt_StgStats = ''; $Oopt_SpecialiseUnboxed = ''; $Oopt_DoSpecialise = '-fspecialise'; $Oopt_FoldrBuild = 1; # On by default! -$Oopt_FB_Support = '-fdo-new-occur-anal -fdo-arity-expand'; +$Oopt_FB_Support = '-fdo-arity-expand'; #$Oopt_FoldrBuildWW = 0; # Off by default $Oopt_FoldrBuildInline = '-fdo-inline-foldr-build'; \end{code} Things to do with C compilers/etc: \begin{code} -$CcUnregd = '$(GHC_DEBUG_HILEV_ASM)'; # our high-level assembler (non-optimising) -$CcRegd = '$(GHC_OPT_HILEV_ASM)'; # our high-level assembler (optimising) -$GccAvailable = $(GHC_GCC_IS_AVAILABLE); # whether GCC avail or not for optimising - +$CcRegd = 'gcc'; @CcBoth_flags = ('-S'); # flags for *any* C compilation @CcInjects = (); -# non-registerizing flags: those for all files, those only for .c files; those only for .hc files -@CcUnregd_flags = ( $GccAvailable ) ? ('-ansi', '-pedantic') : (); -@CcUnregd_flags_c = (); -@CcUnregd_flags_hc= (); - -# ditto; but for registerizing (we must have GCC for this) +# GCC flags: those for all files, those only for .c files; those only for .hc files @CcRegd_flags = ('-ansi', '-D__STG_GCC_REGS__', '-D__STG_TAILJUMPS__'); @CcRegd_flags_c = (); @CcRegd_flags_hc = (); -$As = ''; # assembler is normally the same pgm as used for C compilation +$As = ''; # "assembler" is normally GCC @As_flags = (); -$Lnkr = ''; # linker is normally the same pgm as used for C compilation +$Lnkr = ''; # "linker" is normally GCC @Ld_flags = (); # 'nm' is used for consistency checking (ToDo: mk-world-ify) @@ -283,7 +276,7 @@ $BuildTag = ''; # default is sequential build w/ Appel-style GC %BuildDescr = ('', 'normal sequential', '_p', 'profiling', '_t', 'ticky-ticky profiling', - '_u', 'unregisterized (using portable C only)', +#OLD: '_u', 'unregisterized (using portable C only)', '_mc', 'concurrent', '_mr', 'profiled concurrent', '_mt', 'ticky concurrent', @@ -341,12 +334,15 @@ $BuildTag = ''; # default is sequential build w/ Appel-style GC '_p', 'push(@HsC_flags, \'-fscc-profiling\'); push(@CcBoth_flags, \'-DPROFILING\');', + #and maybe ... + #push(@CcBoth_flags, '-DPROFILING_DETAIL_COUNTS'); + # ticky-ticky sequential '_t', 'push(@HsC_flags, \'-fticky-ticky\'); push(@CcBoth_flags, \'-DTICKY_TICKY\');', - # unregisterized (ToDo????) - '_u', '', +#OLD: # unregisterized (ToDo????) +# '_u', '', # concurrent '_mc', '$StkChkByPageFaultOK = 0; @@ -374,7 +370,8 @@ $BuildTag = ''; # default is sequential build w/ Appel-style GC # GranSim '_mg', '$StkChkByPageFaultOK = 0; - push(@HsC_flags, \'-fconcurrent\'); + push(@HsC_flags, \'-fconcurrent\', \'-fgransim\'); + push(@HsCpp_flags,\'-D__GRANSIM__\', \'-DGRAN\'); push(@Cpp_define, \'-D__CONCURRENT_HASKELL__\', \'-DCONCURRENT\', \'-DGRAN\');', '_2s', 'push (@CcBoth_flags, \'-DGC2s\');', @@ -409,17 +406,17 @@ require special handling. @SysImport_dir = ( $(INSTALLING) ) ? ( "$InstDataDirGhc/imports" ) : ( "$TopPwd/$(CURRENT_DIR)/$(GHC_LIBSRC)/prelude" - ); + , "$TopPwd/$(CURRENT_DIR)/$(GHC_LIBSRC)/required" ); -$ghc_version_info = $(PROJECTVERSION) * 100; -$haskell1_version = 2; # i.e., Haskell 1.2 -@Cpp_define = (); +$GhcVersionInfo = 201; # ToDo: int ($(PROJECTVERSION) * 100); +$Haskell1Version = 3; # i.e., Haskell 1.3 +@Cpp_define = (); @UserLibrary_dir= (); #-L things;... @UserLibrary = (); #-l things asked for by the user @SysLibrary_dir = ( ( $(INSTALLING) ) #-syslib things supplied by the system - ? "$InstLibDirGhc" + ? $InstLibDirGhc : ("$TopPwd/$(CURRENT_DIR)/$(GHC_RUNTIMESRC)", "$TopPwd/$(CURRENT_DIR)/$(GHC_RUNTIMESRC)/gmp", "$TopPwd/$(CURRENT_DIR)/$(GHC_LIBSRC)") @@ -440,35 +437,28 @@ start with. Linking is weird and kept track of separately. Here are the initial defaults applied to all files: \begin{code} -$Do_lit2pgm = 1; -$Do_hscpp = 1; # but we run 'cat' by default (see after arg check) $Cpp_flag_set = 0; # (hack) $Only_preprocess_C = 0; # pretty hackish -$ProduceHi = 1; # but beware magical value "2"! (hack) $PostprocessCcOutput = 0; -$HiDiff_flag= 0; # native code-gen or via C? $HaveNativeCodeGen = $(GHC_WITH_NATIVE_CODEGEN); -$ProduceS = ''; -if ($HaveNativeCodeGen) { - if ($TargetPlatform =~ /^(alpha|sparc)-/) { - $ProduceS = $TargetPlatform; - } -} -$ProduceC = ($ProduceS) ? 0 : 1; +$HscOut = '-C='; # '-C=' ==> .hc output; '-S=' ==> .s output; '-N=' ==> neither +$HscOut = '-S=' + if $HaveNativeCodeGen && $TargetPlatform =~ /^(alpha|sparc|i386)-/; +$ProduceHi = '-hifile='; +$HiOnStdout = 0; +$HiDiff_flag = 0; $CollectingGCstats = 0; $CollectGhcTimings = 0; -$RegisteriseC = ''; # set to 'o', if using optimised C code (only if avail) - # or if generating equiv asm code $DEBUGging = ''; # -DDEBUG and all that it entails (um... not really) $PROFing = ''; # set to p or e if profiling $PROFgroup = ''; # set to group if an explicit -Ggroup specified $PROFauto = ''; # set to relevant hsc flag if -auto or -auto-all $PROFcaf = ''; # set to relevant hsc flag if -caf-all -#UNUSED:$PROFdict = ''; # set to relevant hsc flag if -dict-all $PROFignore_scc = ''; # set to relevant parser flag if explicit sccs ignored +$UNPROFscc_auto = ''; # set to relevant hsc flag if forcing auto sccs without profiling $TICKYing = ''; # set to t if compiling for ticky-ticky profiling $PARing = ''; # set to p if compiling for PAR $CONCURing = ''; # set to c if compiling for CONCURRENT @@ -479,23 +469,22 @@ $Specific_output_file = ''; # set by -o <file>; "-" for stdout $Specific_hi_file = ''; # set by -ohi <file>; "-" for stdout $Specific_dump_file = ''; # set by -odump <file>; "-" for stdout $Using_dump_file = 0; -$Osuffix = '.o'; -$HiSuffix = '.hi'; -$Do_hsp = 2; # 1 for "old" parser; 2 for "new" parser (in hsc) -$Do_hsc = 1; +$Osuffix = ''; # default: use the normal suffix for that kind of output +$HiSuffix = 'hi'; +$SysHiSuffix= 'hi'; +$Do_recomp_chkr = 0; # don't use the recompilatio checker unless asked $Do_cc = -1; # a MAGIC indeterminate value; will be set to 1 or 0. $Do_as = 1; $Do_lnkr = 1; $Keep_hc_file_too = 0; $Keep_s_file_too = 0; -$CompilingPrelude = 0; +$UseGhcInternals = 0; # if 1, may use GHC* modules $SplitObjFiles = 0; $NoOfSplitFiles = 0; $Dump_parser_output = 0; $Dump_raw_asm = 0; -$Dump_asm_insn_counts = 0; -$Dump_asm_globals_info = 0; $Dump_asm_splitting_info = 0; +$NoImplicitPrelude = 0; # and the list of files @Input_file = (); @@ -516,16 +505,16 @@ $LinkChk = 1; # set to 0 if the link check should *not* be done # major & minor version numbers; major numbers must always agree; # minor disagreements yield a warning. -$HsC_major_version = 29; +$HsC_major_version = 30; $HsC_minor_version = 0; -$Cc_major_version = 33; +$Cc_major_version = 35; $Cc_minor_version = 0; # options: these must always agree $HsC_consist_options = ''; # we record, in this order: # Build tag; debugging? $Cc_consist_options = ''; # we record, in this order: - # Build tag; debugging? registerised? + # Build tag; debugging? \end{code} %************************************************************************ @@ -556,11 +545,10 @@ if (grep(/^-user-prelude$/, @ARGV)) { @ARGV); unshift(@ARGV, - '-prelude', + '-fcompiling-ghc-internals=???', # ToDo!!!! '-O', '-fshow-pragma-name-errs', '-fshow-import-specs', - '-fomit-reexported-instances', '-fglasgow-exts', '-genSPECS', '-DUSE_FOLDR_BUILD', @@ -580,25 +568,25 @@ arg: while($_ = $ARGV[0]) { /^-v$/ && do { $Verbose = '-v'; $Time = 'time'; next arg; }; #---------- what phases are to be run ---------------------------------- + /^-short$/ && do { $Do_recomp_chkr = 1; next arg; }; + /^-cpp$/ && do { $Cpp_flag_set = 1; next arg; }; # change the global default: # we won't run cat; we'll run the real thing - /^-C$/ && do { $Do_cc = 0; $Do_as = 0; $Do_lnkr = 0; - $ProduceC = 1; $ProduceS = ''; + /^-C$/ && do { $Do_cc = 0; $Do_as = 0; $Do_lnkr = 0; $HscOut = '-C='; next arg; }; # stop after generating C - /^-noC$/ && do { $ProduceC = 0; $ProduceS = ''; $ProduceHi = 0; + /^-noC$/ && do { $HscOut = '-N='; $ProduceHi = '-nohifile='; $Do_cc = 0; $Do_as = 0; $Do_lnkr = 0; next arg; }; # leave out actual C generation (debugging) [also turns off interface gen] - /^-hi$/ && do { $ProduceHi = 2; next arg; }; + /^-hi$/ && do { $HiOnStdout = 1; $ProduceHi = '-hifile='; next arg; }; # _do_ generate an interface; usually used as: -noC -hi - # NB: magic value "2" for $ProduceHi (hack) - /^-nohi$/ && do { $ProduceHi = 0; next arg; }; + /^-nohi$/ && do { $ProduceHi = '-nohifile='; next arg; }; # don't generate an interface (even if generating C) /^-hi-diffs$/ && do { $HiDiff_flag = 1; next arg; }; @@ -620,24 +608,6 @@ arg: while($_ = $ARGV[0]) { /^-no-link-chk$/ && do { $LinkChk = 0; next arg; }; # don't do consistency-checking after a link - # generate code for a different target architecture; e.g., m68k - # ToDo: de-Glasgow-ize & probably more... -# OLD: -# /^-target$/ && do { $TargetPlatform = &grab_arg_arg('-target', ''); -# if ($TargetPlatform ne $HostPlatform) { -# if ( $TargetPlatform =~ /^m68k-/ ) { -# $CcUnregd = $CcRegd = 'gcc-m68k'; -# } else { -# print STDERR "$Pgm: Can't handle -target $TargetPlatform\n"; -# $Status++; -# } -# } -# next arg; }; - - /^-unregisteri[sz]ed$/ && do { $RegisteriseC = 'no'; - $ProduceC = 1; $ProduceS = ''; # via C, definitely - next arg; }; - /^-tmpdir$/ && do { $Tmp_prefix = &grab_arg_arg('-tmpdir', ''); $Tmp_prefix = "$Tmp_prefix/ghc$$"; $ENV{'TMPDIR'} = $Tmp_prefix; # for those who use it... @@ -650,6 +620,13 @@ arg: while($_ = $ARGV[0]) { # "-o -" sends it to stdout # if <file> has a directory component, that dir must already exist + /^-odir$/ && do { $Specific_output_dir = &grab_arg_arg('-odir', ''); + if (! -d $Specific_output_dir) { + print STDERR "$Pgm: -odir: no such directory: $Specific_output_dir\n"; + $Status++; + } + next arg; }; + /^-o$/ && do { $Specific_output_file = &grab_arg_arg('-o', ''); if ($Specific_output_file ne '-' && $Specific_output_file =~ /(.*)\/[^\/]*$/) { @@ -661,6 +638,13 @@ arg: while($_ = $ARGV[0]) { } next arg; }; + /^-osuf$/ && do { $Osuffix = &grab_arg_arg('-osuf', ''); + if ($Osuffix =~ /\./ ) { + print STDERR "$Pgm: -osuf suffix shouldn't contain a .\n"; + $Status++; + } + next arg; }; + # -ohi <file>; send the interface to <file>; "-ohi -" to send to stdout /^-ohi$/ && do { $Specific_hi_file = &grab_arg_arg('-ohi', ''); if ($Specific_hi_file ne '-' @@ -673,6 +657,20 @@ arg: while($_ = $ARGV[0]) { } next arg; }; + /^-hisuf$/ && do { $HiSuffix = &grab_arg_arg('-hisuf', ''); + if ($HiSuffix =~ /\./ ) { + print STDERR "$Pgm: -hisuf suffix shouldn't contain a .\n"; + $Status++; + } + next arg; }; + /^-hisuf-prelude$/ && do { # as esoteric as they come... + $SysHiSuffix = &grab_arg_arg('-hisuf-prelude', ''); + if ($SysHiSuffix =~ /\./ ) { + print STDERR "$Pgm: -hisuf-prelude suffix shouldn't contain a .\n"; + $Status++; + } + next arg; }; + /^-odump$/ && do { $Specific_dump_file = &grab_arg_arg('-odump', ''); if ($Specific_dump_file =~ /(.*)\/[^\/]*$/) { local($dir_part) = $1; @@ -683,23 +681,6 @@ arg: while($_ = $ARGV[0]) { } next arg; }; - /^-odir$/ && do { $Specific_output_dir = &grab_arg_arg('-odir', ''); - if (! -d $Specific_output_dir) { - print STDERR "$Pgm: -odir: no such directory: $Specific_output_dir\n"; - $Status++; - } - next arg; }; - - /^-osuf$/ && do { $Osuffix = &grab_arg_arg('-osuf', ''); next arg; }; - /^-hisuf$/ && do { $HiSuffix = &grab_arg_arg('-hisuf', ''); - push(@HsP_flags, "-h$HiSuffix"); - next arg; }; - - /^-hisuf-prelude$/ && do { # as esoteric as they come... - local($suffix) = &grab_arg_arg('-hisuf-prelude', ''); - push(@HsP_flags, "-g$suffix"); - next arg; }; - #-------------- scc & Profiling Stuff ---------------------------------- /^-prof$/ && do { $PROFing = 'p'; next arg; }; # profiling -- details later! @@ -717,19 +698,22 @@ arg: while($_ = $ARGV[0]) { $PROFcaf = '-fauto-sccs-on-individual-cafs'; next arg; }; -# UNUSED: -# /^-dict-all/ && do { # generate individual SCC annotations on dictionaries -# $PROFdict = '-fauto-sccs-on-individual-dicts'; -# next arg; }; - /^-ignore-scc$/ && do { # forces ignore of scc annotations even if profiling $PROFignore_scc = '-W'; next arg; }; - /^-G(.*)$/ && do { push(@HsC_flags, $_); # set group for cost centres + /^-G(.*)$/ && do { push(@HsC_flags, "-G=$1"); # set group for cost centres next arg; }; + /^-unprof-scc-auto/ && do { + # generate auto SCCs on top level bindings when not profiling + # used to measure optimisation effects of presence of sccs + $UNPROFscc_auto = ( /-all/ ) + ? '-fauto-sccs-on-all-toplevs' + : '-fauto-sccs-on-exported-toplevs'; + next arg; }; + #--------- ticky/concurrent/parallel ----------------------------------- # we sort out the details a bit later on @@ -816,12 +800,12 @@ arg: while($_ = $ARGV[0]) { /^-syslib(.*)/ && do { local($syslib) = &grab_arg_arg('-syslib',$1); print STDERR "$Pgm: no such system library (-syslib): $syslib\n", - $Status++ unless $syslib =~ /^(hbc|ghc|contrib)$/; + $Status++ unless $syslib =~ /^(hbc|ghc|posix|contrib)$/; unshift(@SysImport_dir, $(INSTALLING) - ? "$InstDataDirGhc/imports/$syslib" - : "$TopPwd/$(CURRENT_DIR)/$(GHC_LIBSRC)/$syslib"); + ? "$InstSysLibDir/$syslib/imports" + : "$TopPwd/hslibs/$syslib/src"); unshift(@SysLibrary, ('-lHS' . $syslib )); @@ -836,10 +820,8 @@ arg: while($_ = $ARGV[0]) { # these change what executable is run for each phase: /^-pgmL(.*)$/ && do { $Unlit = $1; next arg; }; /^-pgmP(.*)$/ && do { $HsCpp = $1; next arg; }; - /^-pgmp(.*)$/ && do { $HsP = $1; next arg; }; /^-pgmC(.*)$/ && do { $HsC = $1; next arg; }; - /^-pgmcO(.*)$/ && do { $CcRegd = $1; next arg; }; - /^-pgmc(.*)$/ && do { $CcUnregd = $1; next arg; }; + /^-pgmcO?(.*)$/ && do { $CcRegd = $1; next arg; }; # the O? for back compat /^-pgma(.*)$/ && do { $As = $1; next arg; }; /^-pgml(.*)$/ && do { $Lnkr = $1; next arg; }; @@ -847,15 +829,8 @@ arg: while($_ = $ARGV[0]) { # these allow arbitrary option-strings to go to any phase: /^-optL(.*)$/ && do { push(@Unlit_flags, $1); next arg; }; /^-optP(.*)$/ && do { push(@HsCpp_flags, $1); next arg; }; - /^-optp(.*)$/ && do { push(@HsP_flags, $1); next arg; }; /^-optCrts(.*)$/&& do { push(@HsC_rts_flags, $1); next arg; }; /^-optC(.*)$/ && do { push(@HsC_flags, $1); next arg; }; - /^-optcNhc(.*)$/ && do { push(@CcUnregd_flags_hc,$1); next arg; }; - /^-optcNc(.*)$/ && do { push(@CcUnregd_flags_c,$1); next arg; }; - /^-optcN(.*)$/ && do { push(@CcUnregd_flags, $1); next arg; }; - /^-optcOhc(.*)$/&& do { push(@CcRegd_flags_hc,$1); next arg; }; - /^-optcOc(.*)$/ && do { push(@CcRegd_flags_c, $1); next arg; }; - /^-optcO(.*)$/ && do { push(@CcRegd_flags, $1); next arg; }; /^-optc(.*)$/ && do { push(@CcBoth_flags, $1); next arg; }; /^-opta(.*)$/ && do { push(@As_flags, $1); next arg; }; /^-optl(.*)$/ && do { push(@Ld_flags, $1); next arg; }; @@ -868,46 +843,27 @@ arg: while($_ = $ARGV[0]) { $genSPECS_flag = $_; next arg; }; - #---------- Haskell parser (hsp) --------------------------------------- - /^-ddump-parser$/ && do { $Dump_parser_output = 1; next arg; }; - #---------- post-Haskell "assembler"------------------------------------ - /^-ddump-raw-asm$/ && do { $Dump_raw_asm = 1; next arg; }; - /^-ddump-asm-insn-counts$/ && do { $Dump_asm_insn_counts = 1; next arg; }; - /^-ddump-asm-globals-info$/ && do { $Dump_asm_globals_info = 1; next arg; }; - + /^-ddump-raw-asm$/ && do { $Dump_raw_asm = 1; next arg; }; /^-ddump-asm-splitting-info$/ && do { $Dump_asm_splitting_info = 1; next arg; }; #---------- Haskell compiler (hsc) ------------------------------------- -# possibly resurrect LATER -# /^-fspat-profiling$/ && do { push(@HsC_flags, '-fticky-ticky'); -# $ProduceS = ''; $ProduceC = 1; # must use C compiler -# push(@CcBoth_flags, '-DDO_SPAT_PROFILING'); -# push(@CcBoth_flags, '-fno-schedule-insns'); # not essential -# next arg; }; - /^-keep-hc-files?-too$/ && do { $Keep_hc_file_too = 1; next arg; }; /^-keep-s-files?-too$/ && do { $Keep_s_file_too = 1; next arg; }; - /^-fhaskell-1\.3$/ && do { $haskell1_version = 3; - push(@HsP_flags, '-3'); - push(@HsC_flags, $_); - $TopClosureFile =~ s/TopClosureXXXX/TopClosure13XXXX/; - unshift(@SysImport_dir, - $(INSTALLING) - ? "$InstDataDirGhc/imports/haskell-1.3" - : "$TopPwd/$(CURRENT_DIR)/$(GHC_LIBSRC)/haskell-1.3"); + /^-fhaskell-1\.3$/ && do { next arg; }; # a no-op right now - unshift(@SysLibrary, '-lHS13'); + /^-fignore-interface-pragmas$/ && do { push(@HsC_flags, $_); next arg; }; - next arg; }; + /^-fno-implicit-prelude$/ && do { $NoImplicitPrelude= 1; push(@HsC_flags, $_); next arg; }; - /^-fno-implicit-prelude$/ && do { push(@HsP_flags, '-P'); next arg; }; - /^-fignore-interface-pragmas$/ && do { push(@HsP_flags, '-p'); next arg; }; + # ToDo: rename to -fcompiling-ghc-internals=<module> + /^-fcompiling-ghc-internals(.*)/ && do { local($m) = &grab_arg_arg('-fcompiling-ghc-internals',$1); + push(@HsC_flags, "-fcompiling-ghc-internals=$m"); + next arg; }; - /^-prelude$/ && do { $CompilingPrelude = 1; - push(@HsC_flags, $_); next arg; }; + /^-fusing-ghc-internals$/ && do { $UsingGhcInternals = 1; next arg; }; /^-user-prelude-force/ && do { # ignore if not -user-prelude next arg; }; @@ -916,37 +872,36 @@ arg: while($_ = $ARGV[0]) { local($sname) = &grab_arg_arg('-split-objs', $1); $sname =~ s/ //g; # no spaces - if ( $TargetPlatform =~ /^(alpha|hppa1\.1|i386|m68k|mips|powerpc|sparc)-/ ) { + if ( $TargetPlatform !~ /^(alpha|hppa1\.1|i386|m68k|mips|powerpc|sparc)-/ ) { + $SplitObjFiles = 0; + print STDERR "WARNING: don't know how to split objects on this platform: $TargetPlatform\n`-split-objs' option ignored\n"; + } else { $SplitObjFiles = 1; - $ProduceS = ''; - $ProduceC = 1; + $HscOut = '-C='; - push(@HsC_flags, "-fglobalise-toplev-names$sname"); + push(@HsC_flags, "-fglobalise-toplev-names=$sname"); push(@CcBoth_flags, '-DUSE_SPLIT_MARKERS'); require('ghc-split.prl') || &tidy_up_and_die(1,"$Pgm: panic: can't load ghc-split.prl!\n"); - } else { - $SplitObjFiles = 0; - print STDERR "WARNING: don't know how to split objects on this platform: $TargetPlatform\n`-split-objs' option ignored\n"; } next arg; }; /^-f(hide-builtin-names|min-builtin-names)$/ && do { push(@HsC_flags, $_); - push(@HsP_flags, '-P'); # don't read Prelude.hi - push(@HsP_flags, '-N'); # allow foo# names +# push(@HsC_flags, '-fno-implicit-prelude'); # don't read Prelude.hi +# push(@HsP_flags, '-N'); # allow foo# names next arg; }; - /^-f(glasgow-exts|hide-builtin-instances)$/ + /^-fglasgow-exts$/ && do { push(@HsC_flags, $_); push(@HsP_flags, '-N'); # push(@HsC_flags, '-fshow-import-specs'); - if ( ! $(INSTALLING) ) { - unshift(@SysImport_dir, - "$TopPwd/$(CURRENT_DIR)/$(GHC_LIBSRC)/glaExts"); - } +# if ( ! $(INSTALLING) ) { +# unshift(@SysImport_dir, +# "$TopPwd/$(CURRENT_DIR)/$(GHC_LIBSRC)/glaExts"); +# } next arg; }; /^-fspeciali[sz]e-unboxed$/ @@ -954,18 +909,16 @@ arg: while($_ = $ARGV[0]) { $Oopt_SpecialiseUnboxed = '-fspecialise-unboxed'; next arg; }; /^-fspeciali[sz]e$/ - && do { $Oopt_DoSpecialise = '-fspecialise'; - next arg; }; + && do { $Oopt_DoSpecialise = '-fspecialise'; next arg; }; /^-fno-speciali[sz]e$/ - && do { $Oopt_DoSpecialise = ''; - next arg; }; + && do { $Oopt_DoSpecialise = ''; next arg; }; # Now the foldr/build options, which are *on* by default (for -O). /^-ffoldr-build$/ && do { $Oopt_FoldrBuild = 1; - $Oopt_FB_Support = '-fdo-new-occur-anal -fdo-arity-expand'; + $Oopt_FB_Support = '-fdo-arity-expand'; #print "Yes F/B\n"; next arg; }; @@ -991,16 +944,10 @@ arg: while($_ = $ARGV[0]) { # && do { $Oopt_FoldrBuildWW = 1; next arg; }; - /^-fasm-(.*)$/ && do { $ProduceS = $1; $ProduceC = 0; # force using nativeGen - push(@HsC_flags, $_); # if from the command line - next arg; }; + # --------------- - /^-fvia-C$/ && do { $ProduceS = ''; $ProduceC = 1; # force using C compiler - next arg; }; - - /^-f(no-)?omit-frame-pointer$/ && do { - unshift(@CcBoth_flags, ( $_ )); - next arg; }; + /^-fasm-(.*)$/ && do { $HscOut = '-S='; next arg; }; # force using nativeGen + /^-fvia-C$/ && do { $HscOut = '-C='; next arg; }; # force using C compiler # --------------- @@ -1027,15 +974,12 @@ arg: while($_ = $ARGV[0]) { if ($num < 2 || $num > 8) { die "Bad experimental flag: $_\n"; } else { - $ProduceS = ''; $ProduceC = 1; # force using C compiler + $HscOut = '-C='; # force using C compiler push(@HsC_flags, "$what$num"); push(@CcRegd_flags, "-D__STG_REGS_AVAIL__=$num"); } next arg; }; -# /^-flambda-lift$/ # so Simon can do some testing; ToDo:rm -# && do { $Oopt_LambdaLift = $_; next arg; }; - # --------------- /^-fno-(.*)$/ && do { push(@HsC_antiflags, "-f$1"); @@ -1059,27 +1003,8 @@ arg: while($_ = $ARGV[0]) { $StolenX86Regs = $1; next arg; }; - /^-mtoggle-sp-mangling/ && do { # for iX86 boxes only; for RTS only - print STDERR "$Pgm: warning: -mtoggle-sp-mangling is no longer supported\n"; -# $SpX86Mangling = 1 - $SpX86Mangling; - next arg; }; - #*************** ... and lots of debugging ones (form: -d* ) - /^-darity-checks$/ && do { - push(@HsC_flags, $_); - push(@CcBoth_flags, '-D__DO_ARITY_CHKS__'); - next arg; }; - /^-darity-checks-C-only$/ && do { - # so we'll have arity-checkable .hc files - # should we decide we need them later... - push(@HsC_flags, '-darity-checks'); - next arg; }; - /^-dno-stk-checks$/ && do { - push(@HsC_flags, '-dno-stk-chks'); - push(@CcBoth_flags, '-D__OMIT_STK_CHKS__'); - next arg; }; - # -d(no-)core-lint is done this way so it is turn-off-able. /^-dcore-lint/ && do { $CoreLint = '-dcore-lint'; next arg; }; /^-dno-core-lint/ && do { $CoreLint = ''; next arg; }; @@ -1093,9 +1018,6 @@ arg: while($_ = $ARGV[0]) { #*************** ... and now all these -R* ones for its runtime system... - /^-Rhbc$/ && do { $RTS_style = 'hbc'; next arg; }; - /^-Rghc$/ && do { $RTS_style = 'ghc'; next arg; }; - /^-Rscale-sizes?(.*)/ && do { $Scale_sizes_by = &grab_arg_arg('-Rscale-sizes', $1); next arg; }; @@ -1149,11 +1071,6 @@ arg: while($_ = $ARGV[0]) { /^-Rghc-timing/ && do { $CollectGhcTimings = 1; next arg; }; #---------- C high-level assembler (gcc) ------------------------------- -# OLD: and dangerous -# /^-g$/ && do { push(@CcBoth_flags, $_); next arg; }; -# /^-(p|pg)$/ && do { push(@CcBoth_flags, $_); push(@Ld_flags, $_); next arg; }; -# /^-(fpic|fPIC)$/ && do { push(@CcBoth_flags, $_); push(@As_flags, $_); next arg; }; - /^-(Wall|ansi|pedantic)$/ && do { push(@CcBoth_flags, $_); next arg; }; # -dgcc-lint is a useful way of making GCC very fussy. @@ -1176,20 +1093,14 @@ arg: while($_ = $ARGV[0]) { #---------- mixed cc and linker magic ---------------------------------- # this optimisation stuff is finally sorted out later on... -# /^-O0$/ && do { # turn all optimisation *OFF* -# $OptLevel = -1; -# $ProduceS = ''; $ProduceC = 1; # force use of C compiler -# next arg; }; - /^-O2-for-C$/ && do { $MinusO2ForC = 1; next arg; }; /^-O[1-2]?$/ && do { +# print STDERR "$Pgm: NOTE: this version of GHC doesn't support -O or -O2\n"; local($opt_lev) = ( /^-O2$/ ) ? 2 : 1; # max 'em $OptLevel = ( $opt_lev > $OptLevel ) ? $opt_lev : $OptLevel; - if ( $OptLevel == 2 ) { # force use of C compiler - $ProduceS = ''; $ProduceC = 1; - } + $HscOut = '-C=' if $OptLevel == 2; # force use of C compiler next arg; }; /^-Onot$/ && do { $OptLevel = 0; next arg; }; # # set it to <no opt> @@ -1278,17 +1189,20 @@ if ($Specific_output_dir ne '' && $Specific_output_file ne '') { if ( ! $PROFing ) { # warn about any scc exprs found (in case scc used as identifier) push(@HsP_flags, '-W'); -} else { - $Oopt_AddAutoSccs = '-fadd-auto-sccs' if $PROFauto; - $Oopt_FinalStgProfilingMassage = '-fmassage-stg-for-profiling'; + # add -auto sccs even if not profiling ! + push(@HsC_flags, $UNPROFscc_auto) if $UNPROFscc_auto; + +} else { push(@HsC_flags, $PROFauto) if $PROFauto; push(@HsC_flags, $PROFcaf) if $PROFcaf; -#UNUSED: push(@HsC_flags, $PROFdict) if $PROFdict; + #push(@HsC_flags, $PROFdict) if $PROFdict; + + $Oopt_FinalStgProfilingMassage = '-fmassage-stg-for-profiling'; push(@HsP_flags, (($PROFignore_scc) ? $PROFignore_scc : '-S')); - if ($SplitObjFiles && ! $CompilingPrelude) { + if ( $SplitObjFiles ) { # can't split with cost centres -- would need global and externs print STDERR "$Pgm: WARNING: splitting objects when profiling will *BREAK* if any _scc_s are present!\n"; # (but it's fine if there aren't any _scc_s around...) @@ -1366,19 +1280,10 @@ It really really wants to be the last STG-to-STG pass that is run. \end{description} \begin{code} -# OLD: -#@HsC_minusO0_flags -# = ( $Oopt_AddAutoSccs, -# '-fsimplify', # would rather *not* run the simplifier (ToDo) -# '\(', '\)', # nothing special at all ???? -# -# $Oopt_FinalStgProfilingMassage -# ); - @HsC_minusNoO_flags = ( '-fsimplify', '\(', - "$Oopt_FB_Support", + $Oopt_FB_Support, # '-falways-float-lets-from-lets', # no idea why this was here (WDP 95/09) '-ffloat-lets-exposing-whnf', '-ffloat-primops-ok', @@ -1386,12 +1291,12 @@ It really really wants to be the last STG-to-STG pass that is run. # '-fdo-lambda-eta-expansion', # too complicated '-freuse-con', # '-flet-to-case', # no strictness analysis, so... - "$Oopt_PedanticBottoms", -# "$Oopt_MonadEtaExpansion", # no thanks + $Oopt_PedanticBottoms, +# $Oopt_MonadEtaExpansion, # no thanks '-fsimpl-uf-use-threshold0', '-fessential-unfoldings-only', -# "$Oopt_UnfoldingUseThreshold", # no thanks - "$Oopt_MaxSimplifierIterations", +# $Oopt_UnfoldingUseThreshold, # no thanks + $Oopt_MaxSimplifierIterations, '\)', $Oopt_AddAutoSccs, # '-ffull-laziness', # removed 95/04 WDP following Andr\'e's lead @@ -1402,19 +1307,17 @@ It really really wants to be the last STG-to-STG pass that is run. @HsC_minusO_flags # NOTE: used for *both* -O and -O2 (some conditional bits) = ( - # initial simplify: mk specialiser and autoscc happy: minimum effort please + # initial simplify: mk specialiser happy: minimum effort please '-fsimplify', '\(', - "$Oopt_FB_Support", + $Oopt_FB_Support, '-fkeep-spec-pragma-ids', # required before specialisation '-fsimpl-uf-use-threshold0', '-fessential-unfoldings-only', '-fmax-simplifier-iterations1', - "$Oopt_PedanticBottoms", + $Oopt_PedanticBottoms, '\)', - $Oopt_AddAutoSccs, # need some basic simplification first - ($Oopt_DoSpecialise) ? ( '-fspecialise-overloaded', $Oopt_SpecialiseUnboxed, @@ -1423,7 +1326,7 @@ It really really wants to be the last STG-to-STG pass that is run. '-fsimplify', # need dependency anal after specialiser ... '\(', # need tossing before calc-inlinings ... - "$Oopt_FB_Support", + $Oopt_FB_Support, '-ffloat-lets-exposing-whnf', '-ffloat-primops-ok', '-fcase-of-case', @@ -1431,10 +1334,10 @@ It really really wants to be the last STG-to-STG pass that is run. '-fdo-eta-reduction', '-fdo-lambda-eta-expansion', '-freuse-con', - "$Oopt_PedanticBottoms", - "$Oopt_MonadEtaExpansion", - "$Oopt_UnfoldingUseThreshold", - "$Oopt_MaxSimplifierIterations", + $Oopt_PedanticBottoms, + $Oopt_MonadEtaExpansion, + $Oopt_UnfoldingUseThreshold, + $Oopt_MaxSimplifierIterations, '\)', '-fcalc-inlinings1', @@ -1444,7 +1347,7 @@ It really really wants to be the last STG-to-STG pass that is run. # '-ffoldr-build-worker-wrapper', # '-fsimplify', # '\(', -# "$Oopt_FB_Support", +# $Oopt_FB_Support, # '-ffloat-lets-exposing-whnf', # '-ffloat-primops-ok', # '-fcase-of-case', @@ -1452,10 +1355,10 @@ It really really wants to be the last STG-to-STG pass that is run. # '-fdo-eta-reduction', # '-fdo-lambda-eta-expansion', # '-freuse-con', -# "$Oopt_PedanticBottoms", -# "$Oopt_MonadEtaExpansion", -# "$Oopt_UnfoldingUseThreshold", -# "$Oopt_MaxSimplifierIterations", +# $Oopt_PedanticBottoms, +# $Oopt_MonadEtaExpansion, +# $Oopt_UnfoldingUseThreshold, +# $Oopt_MaxSimplifierIterations, # '\)', # ) : (), @@ -1470,7 +1373,7 @@ It really really wants to be the last STG-to-STG pass that is run. '\(', '-fignore-inline-pragma', # **** NB! '-fdo-foldr-build', # NB - "$Oopt_FB_Support", + $Oopt_FB_Support, '-ffloat-lets-exposing-whnf', '-ffloat-primops-ok', '-fcase-of-case', @@ -1478,10 +1381,10 @@ It really really wants to be the last STG-to-STG pass that is run. '-fdo-eta-reduction', '-fdo-lambda-eta-expansion', '-freuse-con', - "$Oopt_PedanticBottoms", - "$Oopt_MonadEtaExpansion", - "$Oopt_UnfoldingUseThreshold", - "$Oopt_MaxSimplifierIterations", + $Oopt_PedanticBottoms, + $Oopt_MonadEtaExpansion, + $Oopt_UnfoldingUseThreshold, + $Oopt_MaxSimplifierIterations, '\)', ) : (), @@ -1489,7 +1392,7 @@ It really really wants to be the last STG-to-STG pass that is run. '-fsimplify', '\(', - "$Oopt_FB_Support", + $Oopt_FB_Support, '-ffloat-lets-exposing-whnf', '-ffloat-primops-ok', '-fcase-of-case', @@ -1501,17 +1404,17 @@ It really really wants to be the last STG-to-STG pass that is run. # you need to inline foldr and build ($Oopt_FoldrBuild) ? ('-fdo-foldr-build') : (), # but do reductions if you see them! - "$Oopt_PedanticBottoms", - "$Oopt_MonadEtaExpansion", - "$Oopt_UnfoldingUseThreshold", - "$Oopt_MaxSimplifierIterations", + $Oopt_PedanticBottoms, + $Oopt_MonadEtaExpansion, + $Oopt_UnfoldingUseThreshold, + $Oopt_MaxSimplifierIterations, '\)', '-fstrictness', '-fsimplify', '\(', - "$Oopt_FB_Support", + $Oopt_FB_Support, '-ffloat-lets-exposing-whnf', '-ffloat-primops-ok', '-fcase-of-case', @@ -1520,10 +1423,10 @@ It really really wants to be the last STG-to-STG pass that is run. '-fdo-lambda-eta-expansion', '-freuse-con', '-flet-to-case', # Aha! Only done after strictness analysis - "$Oopt_PedanticBottoms", - "$Oopt_MonadEtaExpansion", - "$Oopt_UnfoldingUseThreshold", - "$Oopt_MaxSimplifierIterations", + $Oopt_PedanticBottoms, + $Oopt_MonadEtaExpansion, + $Oopt_UnfoldingUseThreshold, + $Oopt_MaxSimplifierIterations, '\)', '-ffloat-inwards', @@ -1533,13 +1436,13 @@ It really really wants to be the last STG-to-STG pass that is run. # ( ($OptLevel != 2) # ? '' -# : "-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 \\)" ), +# : "-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 \\)" ), # Final clean-up simplification: '-fsimplify', '\(', - "$Oopt_FB_Support", + $Oopt_FB_Support, '-ffloat-lets-exposing-whnf', '-ffloat-primops-ok', '-fcase-of-case', @@ -1552,10 +1455,10 @@ It really really wants to be the last STG-to-STG pass that is run. $Oopt_FoldrBuildInline, ($Oopt_FoldrBuild) ? ('-fdo-foldr-build') : (), # but still do reductions if you see them! - "$Oopt_PedanticBottoms", - "$Oopt_MonadEtaExpansion", - "$Oopt_UnfoldingUseThreshold", - "$Oopt_MaxSimplifierIterations", + $Oopt_PedanticBottoms, + $Oopt_MonadEtaExpansion, + $Oopt_UnfoldingUseThreshold, + $Oopt_MaxSimplifierIterations, '\)', # '-fstatic-args', @@ -1581,14 +1484,10 @@ It really really wants to be the last STG-to-STG pass that is run. Sort out what we're going to do about optimising. First, the @hsc@ flags and regular @cc@ flags to worry about: \begin{code} -#if ( $OptLevel < 0 ) { - -# &add_Hsc_flags( @HsC_minusO0_flags ); - if ( $OptLevel <= 0 ) { # for this level, we tell the parser -fignore-interface-pragmas - push(@HsP_flags, '-p'); + push(@HsC_flags, '-fignore-interface-pragmas'); # and tell the compiler not to produce them push(@HsC_flags, '-fomit-interface-pragmas'); @@ -1612,31 +1511,24 @@ if ( $OptLevel <= 0 ) { %************************************************************************ %* * -\subsection{Check for registerising, consistency, etc.} +\subsection{Check for consistency, etc.} %* * %************************************************************************ -Are we capable of generating ``registerisable'' C (either using -C or via equivalent native code)? - -\begin{code} -$RegisteriseC = ( $GccAvailable - && $RegisteriseC ne 'no' # not explicitly *un*set... - && ($TargetPlatform =~ /^(alpha|hppa1\.1|i386|m68k|mips|powerpc|sparc)-/) - ) ? 'o' : ''; -\end{code} - Sort out @$BuildTag@, @$PROFing@, @$CONCURing@, @$PARing@, @$GRANing@, @$TICKYing@: \begin{code} if ( $BuildTag ne '' ) { local($b) = $BuildDescr{$BuildTag}; - if ($PROFing eq 'p') { print STDERR "$Pgm: Can't mix $b with profiling.\n"; exit 1; } if ($CONCURing eq 'c') { print STDERR "$Pgm: Can't mix $b with -concurrent.\n"; exit 1; } if ($PARing eq 'p') { print STDERR "$Pgm: Can't mix $b with -parallel.\n"; exit 1; } if ($GRANing eq 'g') { print STDERR "$Pgm: Can't mix $b with -gransim.\n"; exit 1; } if ($TICKYing eq 't') { print STDERR "$Pgm: Can't mix $b with -ticky.\n"; exit 1; } + # ok to have a user-way profiling build + # eval the profiling opts ... but leave user-way BuildTag + if ($PROFing eq 'p') { eval($EvaldSetupOpts{'_p'}); } + } elsif ( $PROFing eq 'p' ) { if ($PARing eq 'p') { print STDERR "$Pgm: Can't do profiling with -parallel.\n"; exit 1; } if ($GRANing eq 'g') { print STDERR "$Pgm: Can't do profiling with -gransim.\n"; exit 1; } @@ -1671,11 +1563,9 @@ if ( $BuildTag ne '' ) { \begin{code} if ( $BuildTag ne '' ) { # something other than normal sequential... - push(@HsP_flags, "-g$BuildTag.hi"); # use appropriate Prelude .hi files + push(@HsP_flags, "-syshisuffix=$BuildTag.hi"); # use appropriate Prelude .hi files - $ProduceC = 1; $ProduceS = ''; # must go via C - -# print STDERR "eval...",$EvaldSetupOpts{$BuildTag},"\n"; + $HscOut = '-C='; # must go via C eval($EvaldSetupOpts{$BuildTag}); } @@ -1684,7 +1574,7 @@ if ( $BuildTag ne '' ) { # something other than normal sequential... Decide what the consistency-checking options are in force for this run: \begin{code} $HsC_consist_options = "${BuildTag},${DEBUGging}"; -$Cc_consist_options = "${BuildTag},${DEBUGging},${RegisteriseC}"; +$Cc_consist_options = "${BuildTag},${DEBUGging}"; \end{code} %************************************************************************ @@ -1704,28 +1594,24 @@ if ($TargetPlatform =~ /^alpha-/) { # we know how to *mangle* asm for alpha unshift(@CcRegd_flags, ('-D__STG_REV_TBLS__')); unshift(@CcRegd_flags, ('-DSTACK_CHECK_BY_PAGE_FAULT=1')) if $StkChkByPageFaultOK; - unshift(@CcBoth_flags, ('-static')) if $GccAvailable; + unshift(@CcBoth_flags, ('-static')); } elsif ($TargetPlatform =~ /^hppa/) { # we know how to *mangle* asm for hppa unshift(@CcRegd_flags, ('-D__STG_REV_TBLS__')); - unshift(@CcBoth_flags, ('-static')) if $GccAvailable; + unshift(@CcBoth_flags, ('-static')); # We don't put in '-mlong-calls', because it's only # needed for very big modules (sigh), and we don't want # to hobble ourselves further on all the other modules # (most of them). - unshift(@CcBoth_flags, ('-D_HPUX_SOURCE')) if $GccAvailable; + unshift(@CcBoth_flags, ('-D_HPUX_SOURCE')); # ___HPUX_SOURCE, not _HPUX_SOURCE, is #defined if -ansi! # (very nice, but too bad the HP /usr/include files don't agree.) } elsif ($TargetPlatform =~ /^i386-/) { # we know how to *mangle* asm for X86 unshift(@CcRegd_flags, ('-D__STG_REV_TBLS__')); - unshift(@CcRegd_flags, ('-DSTACK_CHECK_BY_PAGE_FAULT=1')) - if $StkChkByPageFaultOK && $TargetPlatform !~ /linux/; - # NB: cannot do required signal magic on Linux for such stk chks */ - - unshift(@CcRegd_flags, ('-m486')); # not worth not doing + unshift(@CcRegd_flags, ('-DSTACK_CHECK_BY_PAGE_FAULT=1')) if $StkChkByPageFaultOK; # -fno-defer-pop : basically the same game as for m68k # @@ -1737,8 +1623,6 @@ if ($TargetPlatform =~ /^alpha-/) { unshift(@CcRegd_flags, '-fomit-frame-pointer'); unshift(@CcRegd_flags, "-DSTOLEN_X86_REGS=$StolenX86Regs"); - unshift(@CcBoth_flags, ('-static')) if $GccAvailable; # maybe unnecessary??? - } elsif ($TargetPlatform =~ /^m68k-/) { # we know how to *mangle* asm for m68k unshift (@CcRegd_flags, ('-D__STG_REV_TBLS__')); @@ -1759,6 +1643,12 @@ if ($TargetPlatform =~ /^alpha-/) { # maybe gives reg alloc a better time # also: -fno-defer-pop is not sufficiently well-behaved without it +} elsif ($TargetPlatform =~ /^mips-/) { + # we (hope to) know how to *mangle* asm for MIPSen + unshift(@CcRegd_flags, ('-D__STG_REV_TBLS__')); + unshift(@CcRegd_flags, ('-DSTACK_CHECK_BY_PAGE_FAULT=1')) if $StkChkByPageFaultOK; + unshift(@CcBoth_flags, ('-static')); + } elsif ($TargetPlatform =~ /^powerpc-/) { # we know how to *mangle* asm for PowerPC unshift(@CcRegd_flags, ('-D__STG_REV_TBLS__')); @@ -1769,11 +1659,6 @@ if ($TargetPlatform =~ /^alpha-/) { unshift(@CcRegd_flags, ('-D__STG_REV_TBLS__')); unshift(@CcRegd_flags, ('-DSTACK_CHECK_BY_PAGE_FAULT=1')) if $StkChkByPageFaultOK; -} elsif ($TargetPlatform =~ /^mips-/) { - # we (hope to) know how to *mangle* asm for MIPSen - unshift(@CcRegd_flags, ('-D__STG_REV_TBLS__')); - unshift(@CcRegd_flags, ('-DSTACK_CHECK_BY_PAGE_FAULT=1')) if $StkChkByPageFaultOK; - unshift(@CcBoth_flags, ('-static')) if $GccAvailable; } \end{code} @@ -1783,36 +1668,27 @@ Should really be whether or not we prepend underscores to global symbols, not an architecture test. (JSM) \begin{code} +$Under = ( $TargetPlatform =~ /^alpha-/ + || $TargetPlatform =~ /^hppa/ + || $TargetPlatform =~ /^mips-sgi-irix/ + || $TargetPlatform =~ /^powerpc-/ + || $TargetPlatform =~ /-solaris/ + || $TargetPlatform =~ /-linux$/ + ) + ? '' : '_'; + unshift(@Ld_flags, - ( $TargetPlatform =~ /^alpha-/ - || $TargetPlatform =~ /^hppa/ - || $TargetPlatform =~ /^mips-sgi-irix/ - || $TargetPlatform =~ /^powerpc-/ - || $TargetPlatform =~ /-solaris/ - ) - ? (($Ld_main) ? ( - '-u', 'Main_' . $Ld_main . '_closure', - ) : (), - '-u', 'unsafePerformPrimIO_fast1', - '-u', 'Nil_closure', - '-u', 'IZh_static_info', - '-u', 'False_inregs_info', - '-u', 'True_inregs_info', - '-u', 'CZh_static_info', - '-u', 'DEBUG_REGS') # just for fun, now... - - # nice friendly a.out machines... - : (($Ld_main) ? ( - '-u', '_Main_' . $Ld_main . '_closure', + (($Ld_main) ? ( + '-u', "${Under}Main_" . $Ld_main . '_closure', ) : (), - '-u', '_unsafePerformPrimIO_fast1', - '-u', '_Nil_closure', - '-u', '_IZh_static_info', - '-u', '_False_inregs_info', - '-u', '_True_inregs_info', - '-u', '_CZh_static_info', - '-u', '_DEBUG_REGS') - ); + '-u', "${Under}GHCbase_unsafePerformPrimIO_fast1", + '-u', "${Under}Prelude_Z91Z93_closure", # i.e., [] + '-u', "${Under}Prelude_IZh_static_info", + '-u', "${Under}Prelude_False_inregs_info", + '-u', "${Under}Prelude_True_inregs_info", + '-u', "${Under}Prelude_CZh_static_info", + '-u', "${Under}DEBUG_REGS")) + ; # just for fun, now... \end{code} %************************************************************************ @@ -1827,19 +1703,18 @@ Ready for Business. \begin{code} # default includes must be added AFTER option processing -if ( $(INSTALLING) ) { +if ( ! $(INSTALLING) ) { + push (@Include_dir, "$TopPwd/$(CURRENT_DIR)/$(GHC_INCLUDESRC)"); +} else { push (@Include_dir, "$InstLibDirGhc/includes"); push (@Include_dir, "$InstDataDirGhc/includes"); - -} else { - push (@Include_dir, "$TopPwd/$(CURRENT_DIR)/$(GHC_INCLUDESRC)"); } \end{code} \begin{code} local($f); foreach $f (@SysLibrary) { - $f .= "${BuildTag}" if $f =~ /^-lHS/; + $f .= $BuildTag if $f =~ /^-lHS/; } # fiddle the TopClosure file name... @@ -1896,7 +1771,7 @@ Record largest specific heapsize, if any. $Specific_heap_size = $Specific_heap_size * $Scale_sizes_by; push(@HsC_rts_flags, '-H'.$Specific_heap_size); $Specific_stk_size = $Specific_stk_size * $Scale_sizes_by; -push(@HsC_rts_flags, (($RTS_style eq 'ghc') ? '-K' : '-A').$Specific_stk_size); +push(@HsC_rts_flags, "-K$Specific_stk_size"); # hack to avoid running hscpp $HsCpp = $Cat if ! $Cpp_flag_set; @@ -1906,15 +1781,19 @@ If no input or link files seen, then we let 'em feed in stdin; this is mainly for debugging. \begin{code} if ($#Input_file < 0 && $#Link_file < 0) { - push(@Input_file, '-'); + @Input_file = ( '-' ); + + open(INF, "> $Tmp_prefix.hs") || &tidy_up_and_die(1,"Can't open $Tmp_prefix.hs\n"); + print STDERR "Enter your Haskell program, end with ^D (on a line of its own):\n"; + while (<>) { print INF $_; } + close(INF) || &tidy_up_and_die(1,"Failed writing to $Tmp_prefix.hs\n"); } \end{code} Tell the world who we are, if they asked. \begin{code} -if ($Verbose) { - print STDERR "$(PROJECTNAME), version $(PROJECTVERSION) $(PROJECTPATCHLEVEL)\n"; -} +print STDERR "$(PROJECTNAME), version $(PROJECTVERSION) $(PROJECTPATCHLEVEL)\n" + if $Verbose; \end{code} %************************************************************************ @@ -1940,19 +1819,18 @@ if ( $Status > 0 ) { # don't link if there were errors... Link if appropriate. \begin{code} if ($Do_lnkr) { - local($libdirs); + local($libdirs) = ''; + # glue them together: push(@UserLibrary_dir, @SysLibrary_dir); - if ($#UserLibrary_dir < 0) { - $libdirs = ''; - } else { - $libdirs = '-L' . join(' -L',@UserLibrary_dir); - } + + $libdirs = '-L' . join(' -L',@UserLibrary_dir) if $#UserLibrary_dir >= 0; + # for a linker, use an explicitly given one, or the going C compiler ... - local($lnkr) = ( $Lnkr ) ? $Lnkr : ($RegisteriseC ? $CcRegd : $CcUnregd ); + local($lnkr) = ( $Lnkr ) ? $Lnkr : $CcRegd; - local($output)= ($Specific_output_file ne '') ? "-o $Specific_output_file" : ''; - @Files_to_tidy = ($Specific_output_file ne '') ? "$Specific_output_file" : 'a.out'; + local($output) = ($Specific_output_file ne '') ? "-o $Specific_output_file" : ''; + @Files_to_tidy = ($Specific_output_file ne '') ? $Specific_output_file : 'a.out'; local($to_do) = "$lnkr $Verbose @Ld_flags $output @Link_file $TopClosureFile $libdirs @UserLibrary @SysLibrary"; &run_something($to_do, 'Linker'); @@ -1990,7 +1868,7 @@ if ($Do_lnkr) { $pvm_executable = $ENV{'PVM_ROOT'} . '/bin/' . $ENV{'PVM_ARCH'} . "/$pvm_executable"; - &run_something("rm -f $pvm_executable; cp -p $executable $pvm_executable && rm -f $executable", 'Moving binary to PVM land'); + &run_something("$Rm -f $pvm_executable; $Cp -p $executable $pvm_executable && $Rm -f $executable", 'Moving binary to PVM land'); # OK, now create the magic script for "$executable" open(EXEC, "> $executable") || &tidy_up_and_die(1,"$Pgm: couldn't open $executable to write!\n"); @@ -2042,7 +1920,7 @@ print STDERR "Exec failed!!!: $SysMan $debug $nprocessors @nonPVM_args\n"; exit(1); EOSCRIPT2 close(EXEC) || die "Failed closing $executable\n"; - chmod 0755, "$executable"; + chmod 0755, $executable; } } @@ -2059,452 +1937,383 @@ exit $Status; # will still be 0 if all went well \begin{code} sub ProcessInputFile { - local($ifile) = @_; # input file name - local($ifile_root); # root of or basename of input file - local($ifile_root_file); # non-directory part of $ifile_root + local($ifile) = @_; # input file name + local($ifile_root); # root of or basename of input file + local($ofile_target); # ultimate output file we hope to produce + # from input file (need to know for recomp + # checking purposes) + local($hifile_target);# ditto (but .hi file) \end{code} Handle the weirdity of input from stdin. \begin{code} - if ($ifile eq '-') { - open(INF, "> $Tmp_prefix.hs") || &tidy_up_and_die(1,"Can't open $Tmp_prefix.hs\n"); - print STDERR "Enter your Haskell program, end with ^D (on a line of its own):\n"; - while (<>) { print INF $_; } - close(INF) || &tidy_up_and_die(1,"Failed writing to $Tmp_prefix.hs\n"); - $ifile = "$Tmp_prefix.hs"; - $ifile_root = '_stdin'; - $ifile_root_file = $ifile_root; + if ($ifile ne '-') { + ($ifile_root = $ifile) =~ s/\.[^\.\/]+$//; + $ofile_target = # may be reset later... + ($Specific_output_file ne '' && ! $Do_lnkr) + ? $Specific_output_file + : &odir_ify($ifile_root, 'o'); + $hifile_target= ($Specific_hi_file ne '') + ? $Specific_hi_file + : "$ifile_root.$HiSuffix"; # ToDo: odirify? + # NB: may change if $ifile_root isn't module name (??) } else { - ($ifile_root = $ifile) =~ s/\.[^\.\/]+$//; - ($ifile_root_file = $ifile_root) =~ s|.*/||; + $ifile = "$Tmp_prefix.hs"; # we know that's where we put the input + $ifile_root = '_stdin'; + $ofile_target = '_stdout'; # gratuitous? + $hifile_target= '_stdout'; # ditto? } \end{code} -We now decide what phases of the compilation system we will run over -this file. The defaults are the ones established when processing flags. -(That established what the last phase run for all files is.) +We need to decide what phases of the compilation system we will run +over this file. The defaults are the ones established when processing +flags. (That established what the last phase run for all files is.) -The lower-case names are the local ones (as is usual), just for this -one file. +We do the pre-recompilation-checker phases here; the rest later. \begin{code} - local($do_lit2pgm) = $Do_lit2pgm; - local($do_hscpp) = $Do_hscpp; - local($do_hsp) = $Do_hsp; - local($do_hsc) = $Do_hsc; - local($do_as) = $Do_as; - local($do_cc) = ( $Do_cc != -1) # i.e., it was set explicitly - ? $Do_cc - : ( ($ProduceC) ? 1 : 0 ); \end{code} Look at the suffix and decide what initial phases of compilation may be dropped off for this file. Also the rather boring business of which files are coming-in/going-out. + +Again, we'll do the post-recompilation-checker parts of this later. \begin{code} + local($do_lit2pgm) = ($ifile =~ /\.lhs$/) ? 1 : 0; + local($do_hscpp) = 1; # but "hscpp" might really be "cat" + local($do_hsc) = 1; + local($do_cc) = ( $Do_cc != -1) # i.e., it was set explicitly + ? $Do_cc + : ( ($HscOut eq '-C=') ? 1 : 0 ); + local($do_as) = $Do_as; + # names of the files to stuff between phases # defaults are temporaries local($in_lit2pgm) = $ifile; local($lit2pgm_hscpp) = "$Tmp_prefix.lpp"; - local($hscpp_hsp) = "$Tmp_prefix.cpp"; - local($hsp_hsc) = "$Tmp_prefix.hsp"; - local($hsc_cc) = "$Tmp_prefix.hc"; - - # to help C compilers grok .hc files [ToDo: de-hackify] - local($cc_help) = "ghc$$.c"; - local($cc_help_s) = "ghc$$.s"; - - local($hsc_hi) = "$Tmp_prefix$HiSuffix"; + local($hscpp_hsc) = "$Tmp_prefix.cpp"; + local($hsc_out) = ( $HscOut eq '-C=' ) ? "$Tmp_prefix.hc" : "$Tmp_prefix.s" ; + local($hsc_hi) = "$Tmp_prefix.hi"; local($cc_as_o) = "${Tmp_prefix}_o.s"; # temporary for raw .s file if opt C - local($cc_as) = "$Tmp_prefix.s"; - local($as_out) = ($Specific_output_file ne '' && ! $Do_lnkr) - ? $Specific_output_file - : &odir_ify("${ifile_root}${Osuffix}"); + local($cc_as) = "$Tmp_prefix.s"; # mangled or hsc-produced .s code + local($as_out) = $ofile_target; - local($is_hc_file) = 1; #Is the C code .hc or .c + local($is_hc_file) = 1; #Is the C code .hc or .c? Assume .hc for now if ($ifile =~ /\.lhs$/) { - push(@Link_file, &odir_ify("${ifile_root}${Osuffix}")); + ; # nothing to change } elsif ($ifile =~ /\.hs$/) { $do_lit2pgm = 0; $lit2pgm_hscpp = $ifile; - push(@Link_file, &odir_ify("${ifile_root}${Osuffix}")); } elsif ($ifile =~ /\.hc$/) { - $do_lit2pgm = 0; $do_hscpp = 0; $do_hsp = 0; $do_hsc = 0; $do_cc = 1; - $hsc_cc = $ifile; - push(@Link_file, &odir_ify("${ifile_root}${Osuffix}")); + $do_lit2pgm = 0; $do_hscpp = 0; $do_hsc = 0; $do_cc = 1; + $hsc_out = $ifile; } elsif ($ifile =~ /\.c$/) { - $do_lit2pgm = 0; $do_hscpp = 0; $do_hsp = 0; $do_hsc = 0; $do_cc = 1; - $hsc_cc = $ifile; $is_hc_file = 0; - push(@Link_file, &odir_ify("${ifile_root}${Osuffix}")); + $do_lit2pgm = 0; $do_hscpp = 0; $do_hsc = 0; $do_cc = 1; + $hsc_out = $ifile; $is_hc_file = 0; } elsif ($ifile =~ /\.s$/) { - $do_lit2pgm = 0; $do_hscpp = 0; $do_hsp = 0; $do_hsc = 0; $do_cc = 0; + $do_lit2pgm = 0; $do_hscpp = 0; $do_hsc = 0; $do_cc = 0; $cc_as = $ifile; - push(@Link_file, &odir_ify("${ifile_root}${Osuffix}")); - } else { - if ($ifile !~ /\.a$/) { - print STDERR "$Pgm: don't recognise suffix on `$ifile'; passing it through to linker\n"; - } - $do_lit2pgm = 0; $do_hscpp = 0; $do_hsp = 0; $do_hsc = 0; $do_cc = 0; $do_as = 0; - push(@Link_file, $ifile); + } else { # don't know what it is, but nothing to do herein... + $do_lit2pgm = 0; $do_hscpp = 0; $do_hsc = 0; $do_cc = 0; $do_as = 0; } + + # OK, have a bash on the first two phases: + &runLit2pgm($in_lit2pgm, $lit2pgm_hscpp) + if $do_lit2pgm; + + &runHscpp($in_lit2pgm, $lit2pgm_hscpp, $hscpp_hsc) + if $do_hscpp; \end{code} +We now think about whether to run hsc/cc or not (when hsc produces .s +stuff, it effectively takes the place of both phases). + To get the output file name right: for each phase that we are {\em -not} going to run, set its input (i.e., the output of its preceding phase) to -@"$ifile_root.<suffix>"@. +not} going to run, set its input (i.e., the output of its preceding +phase) to @"$ifile_root.<suffix>"@. \begin{code} - # lit2pgm -- no preceding phase - if (! $do_hscpp) { - $lit2pgm_hscpp = "$ifile_root.lpp????"; # not done - } - if (! $do_hsp) { - $hscpp_hsp = "$ifile_root.cpp????"; # not done - } - if (! $do_hsc) { - $hsp_hsc = "$ifile_root.hsp????"; # not done - } - if (! $do_cc) { - $hsc_cc = &odir_ify("$ifile_root.hc"); - } - if (! $do_as) { - if ($Specific_output_file ne '') { - $cc_as = $Specific_output_file; - } else { - $cc_as = &odir_ify(( $Only_preprocess_C ) ? "$ifile_root.i" : "$ifile_root.s"); - } - } -\end{code} + local($going_interactive) = $HscOut eq '-N=' || $ifile_root eq '_stdin'; -OK, now do it! Note that we don't come back from a @run_something@ if -it fails. -\begin{code} - if ($do_lit2pgm) { - local($to_do) = "echo '#line 1 \"$in_lit2pgm\"' > $lit2pgm_hscpp; ". - "$Unlit @Unlit_flags $in_lit2pgm - >> $lit2pgm_hscpp"; - @Files_to_tidy = ( $lit2pgm_hscpp ); - &run_something($to_do, 'literate pre-processor'); - } - if ($do_hscpp) { - # ToDo: specific output? - if ($HsCpp eq $Cat) { - local($to_do) = "echo '#line 1 \"$in_lit2pgm\"' > $hscpp_hsp; ". - "$HsCpp $lit2pgm_hscpp >> $hscpp_hsp"; - @Files_to_tidy = ( $hscpp_hsp ); - &run_something($to_do, 'Ineffective C pre-processor'); - } else { - local($includes) = '-I' . join(' -I',@Include_dir); - local($to_do) = "echo '#line 1 \"$in_lit2pgm\"' > $hscpp_hsp; ". - "$HsCpp $Verbose $genSPECS_flag @HsCpp_flags -D__HASKELL1__=$haskell1_version -D__GLASGOW_HASKELL__=$ghc_version_info $includes $lit2pgm_hscpp >> $hscpp_hsp"; - @Files_to_tidy = ( $hscpp_hsp ); - &run_something($to_do, 'Haskellised C pre-processor'); - } - } - if ($do_hsp) { - # glue imports onto HsP_flags - # if new parser, then put a comma on the front of all of them. - local($hsprefix) = ($do_hsp == 2) ? ',' : ''; - - foreach $a ( @HsP_flags ) { $a = "$hsprefix$a" unless $a =~ /^,/; } - foreach $dir ( @Import_dir ) { push(@HsP_flags, "$hsprefix-I$dir"); } - foreach $dir ( @SysImport_dir ) { push(@HsP_flags, "$hsprefix-J$dir"); } + if (! $do_cc && ! $do_as) { # stopping after hsc + $hsc_out = ($Specific_output_file ne '') + ? $Specific_output_file + : &odir_ify($ifile_root, ($HscOut eq '-C=') ? 'hc' : 's'); + + $ofile_target = $hsc_out; # reset } - if ($do_hsp == 1) { # "old" parser - local($to_do) = "$HsP $Verbose @HsP_flags $hscpp_hsp > $hsp_hsc"; - @Files_to_tidy = ( $hsp_hsc ); - &run_something($to_do, 'Haskell parser'); - if ($Dump_parser_output) { - print STDERR `$Cat $hsp_hsc`; - } - @HsP_flags = (); # reset! + if (! $do_as) { # stopping after gcc (or hsc) + $cc_as = ($Specific_output_file ne '') + ? $Specific_output_file + : &odir_ify($ifile_root, ( $Only_preprocess_C ) ? 'i' : 's'); + + $ofile_target = $cc_as; # reset } - if ($do_hsc) { - # here, we may produce .hc and/or .hi files - local($output) = ''; - local($c_source) = "$ifile_root.hc"; - local($c_output) = $hsc_cc; # defaults - local($s_output) = $cc_as; - local($hi_output) = "$ifile_root$HiSuffix"; - local($going_interactive) = 0; - - if ($Specific_output_file ne '' && ! $do_cc) { - $c_source = $c_output = $Specific_output_file; - @Files_to_tidy = ( $Specific_output_file ) if $Specific_output_file ne '-'; - } - if ($Specific_hi_file ne '') { - # we change the suffix (-hisuf) even if a specific -ohi file: - $Specific_hi_file =~ s/\.hi$/$HiSuffix/; - $hi_output = $Specific_hi_file; - @Files_to_tidy = ( $Specific_hi_file ) if $Specific_hi_file ne '-'; - } - if ( ! ($ProduceC || $ProduceS) - || $ifile_root eq '_stdin' # going interactive... - || ($c_output eq '-' && $hi_output eq '-')) { - $going_interactive = 1; -#OLD: $output = '1>&2'; # interactive/debugging, to stderr - @Files_to_tidy = (); - # don't need .hi (unless magic value "2" says we wanted it anyway): - if ( $ProduceHi == 2 ) { - $output .= " -hi$hsc_hi"; - unlink($hsc_hi); # needs to be cleared; will be appended to - } else { - $ProduceHi = 0; - } - $do_cc = 0; $do_as = 0; $Do_lnkr = 0; # and we won't go any further... - } +\end{code} - if ( ! $going_interactive ) { - if ( $ProduceHi ) { - # we always go to a temp file for these (for later diff'ing) - $output = "-hi$hsc_hi"; - unlink($hsc_hi); # needs to be cleared; will be appended to - @Files_to_tidy = ( $hsc_hi ); - } - if ( $ProduceC ) { - $output .= " -C$c_output"; - push(@Files_to_tidy, $c_output); - - open(CFILE, "> $c_output") || &tidy_up_and_die(1,"$Pgm: failed to open `$c_output' (to write)\n"); - print CFILE "#line 2 \"$c_source\"\n"; - close(CFILE) || &tidy_up_and_die(1,"Failed writing to $c_output\n"); - # the "real" C output will then be appended - } - if ( $ProduceS ) { - $output .= " -fasm-$ProduceS -S$s_output"; - push(@Files_to_tidy, $s_output); - - # ToDo: ummm,... this isn't doing anything (WDP 94/11) - open(SFILE, "> $s_output") || &tidy_up_and_die(1,"$Pgm: failed to open `$s_output' (to write)\n"); - close(SFILE) || &tidy_up_and_die(1,"Failed writing to $s_output\n"); - # the "real" assembler output will then be appended - } - } +Check if hsc needs to be run at all. - # if we're compiling foo.hs, we want the GC stats to end up in foo.stat - if ( $CollectingGCstats ) { - if ($RTS_style eq 'hbc') { - push(@HsC_rts_flags, '-S'); # puts it in "STAT" - } else { - push(@HsC_rts_flags, "-S$ifile_root.stat"); - push(@Files_to_tidy, "$ifile_root.stat"); - } - } +\begin{code} + local($more_processing_required) = 1; - if ( $CollectGhcTimings ) { # assume $RTS_style eq 'ghc' - # emit nofibbish time/bytes-alloc stats to stderr; - # see later .stat file post-processing - push(@HsC_rts_flags, "-s$Tmp_prefix.stat"); - push(@Files_to_tidy, "$Tmp_prefix.stat"); - } + if ( $Do_recomp_chkr && $do_hsc && ! $going_interactive ) { + # recompilation-checking is important enough to live off by itself + require('ghc-recomp.prl') + || &tidy_up_and_die(1,"$Pgm: panic: can't load ghc-recomp.prl!\n"); - local($dump); - if ($Specific_dump_file ne '') { - $dump = "2>> $Specific_dump_file"; - $Using_dump_file = 1; - } else { - $dump = ''; - } - - local($to_do); - if ($RTS_style eq 'hbc') { - # NB: no parser flags - $to_do = "$HsC < $hsp_hsc $dump @HsC_rts_flags - @HsC_flags $CoreLint $Verbose $output"; - } elsif ($do_hsp == 1) { # old style parser -- no HsP_flags - $to_do = "$HsC < $hsp_hsc $dump @HsC_flags $CoreLint $Verbose $output +RTS @HsC_rts_flags"; - } else { # new style - $to_do = "$HsC ,-H @HsP_flags ,$hscpp_hsp $dump @HsC_flags $CoreLint $Verbose $output +RTS @HsC_rts_flags"; - } - &run_something($to_do, 'Haskell compiler'); + $more_processing_required + = &runRecompChkr($ifile, $hscpp_hsc, $ifile_root, $ofile_target, $hifile_target); - # compensate further for HBC's -S rts opt: - if ($CollectingGCstats && $RTS_style eq 'hbc') { - unlink("$ifile_root.stat"); - rename('STAT', "$ifile_root.stat"); - } + print STDERR "$Pgm:recompile: NOT NEEDED!\n" if ! $more_processing_required; + } - # finish business w/ nofibbish time/bytes-alloc stats - &process_ghc_timings() if $CollectGhcTimings; + $do_hsc = 0, $do_cc = 0, $do_as = 0 if ! $more_processing_required; +\end{code} - # if non-interactive, heave in the consistency info at the end - # NB: pretty hackish (depends on how $output is set) - if ( ! $going_interactive ) { - if ( $ProduceC ) { - $to_do = "echo 'static char ghc_hsc_ID[] = \"\@(#)hsc $ifile\t$HsC_major_version.$HsC_minor_version,$HsC_consist_options\";' >> $c_output"; - } - if ( $ProduceS ) { - local($consist) = "hsc.$ifile.$HsC_major_version.$HsC_minor_version.$HsC_consist_options"; - $consist =~ s/,/./g; - $consist =~ s/\//./g; - $consist =~ s/-/_/g; - $consist =~ s/[^A-Za-z0-9_.]/ZZ/g; # ToDo: properly? - $to_do = "echo '\n\t.text\n$consist:' >> $s_output"; - } - &run_something($to_do, 'Pin on Haskell consistency info'); - } +\begin{code} + if ( $do_hsc ) { + + &runHsc($ifile_root, $hsc_out, $hsc_hi, $going_interactive); - # call the special mangler to produce the .hi/.h(h?) files... - &diff_hi_file($hsc_hi, $hi_output) - if $ProduceHi == 1 && ! $going_interactive; -#OLD: &extract_c_and_hi_files("$Tmp_prefix.hsc", $c_output, $hi_output, $c_source) + # interface-handling is important enough to live off by itself + require('ghc-iface.prl') + || &tidy_up_and_die(1,"$Pgm: panic: can't load ghc-iface.prl!\n"); - # if we produced an interface file "no matter what", - # print what we got on stderr (ToDo: honor -ohi flag) - if ( $ProduceHi == 2 ) { - print STDERR `$Cat $hsc_hi`; - } + &postprocessHiFile($hsc_hi, $hifile_target, $going_interactive); # save a copy of the .hc file, even if we are carrying on... - if ($ProduceC && $do_cc && $Keep_hc_file_too) { - local($to_do) = "$(RM) $ifile_root.hc; cp $c_output $ifile_root.hc"; + if ($HscOut eq '-C=' && $do_cc && $Keep_hc_file_too) { + local($to_do) = "$Rm $ifile_root.hc; $Cp $hsc_out $ifile_root.hc"; &run_something($to_do, 'Saving copy of .hc file'); } # save a copy of the .s file, even if we are carrying on... - if ($ProduceS && $do_as && $Keep_s_file_too) { - local($to_do) = "$(RM) $ifile_root.s; cp $cc_as $ifile_root.s"; + if ($HscOut eq '-S=' && $do_as && $Keep_s_file_too) { + local($to_do) = "$Rm $ifile_root.s; $Cp $hsc_out $ifile_root.s"; &run_something($to_do, 'Saving copy of .s file'); } # if we're going to split up object files, # we inject split markers into the .hc file now - if ( $ProduceC && $SplitObjFiles ) { - &inject_split_markers ( $c_output ); + if ( $HscOut eq '-C=' && $SplitObjFiles ) { + &inject_split_markers ( $hsc_out ); } } + if ($do_cc) { + &runGcc ($is_hc_file, $hsc_out, $cc_as_o); + &runMangler($is_hc_file, $cc_as_o, $cc_as, $ifile_root); + } + + &split_asm_file($cc_as) if $do_as && $SplitObjFiles; + + &runAs($as_out, $ifile_root) if $do_as; +\end{code} + +Finally, decide what to queue up for linker input. +\begin{code} + # tentatively assume we will eventually produce linker input: + push(@Link_file, &odir_ify($ifile_root, 'o')); + + if ($ifile !~ /\.(lhs|hs|hc|c|s)$/) { + print STDERR "$Pgm: don't recognise suffix on `$ifile'; passing it through to linker\n" + if $ifile !~ /\.a$/; + + # oops; we tentatively pushed the wrong thing; fix & do the right thing + pop(@Link_file); push(@Link_file, $ifile); + } + +} # end of ProcessInputFile +\end{code} + +%************************************************************************ +%* * +\section[Driver-run-phases]{Routines to run the various phases} +%* * +%************************************************************************ + +\begin{code} +sub runLit2pgm { + local($in_lit2pgm, $lit2pgm_hscpp) = @_; + + local($to_do) = "echo '#line 1 \"$in_lit2pgm\"' > $lit2pgm_hscpp && ". + "$Unlit @Unlit_flags $in_lit2pgm - >> $lit2pgm_hscpp"; + @Files_to_tidy = ( $lit2pgm_hscpp ); + + &run_something($to_do, 'literate pre-processor'); +} +\end{code} + +\begin{code} +sub runHscpp { + local($in_lit2pgm, $lit2pgm_hscpp, $hscpp_hsc) = @_; + + local($to_do); + + if ($HsCpp eq $Cat) { + $to_do = "echo '#line 1 \"$in_lit2pgm\"' > $hscpp_hsc && ". + "$HsCpp $lit2pgm_hscpp >> $hscpp_hsc"; + @Files_to_tidy = ( $hscpp_hsc ); + &run_something($to_do, 'Ineffective C pre-processor'); + } else { local($includes) = '-I' . join(' -I',@Include_dir); - local($cc); - local($s_output); - local($c_flags) = "@CcBoth_flags"; - local($ddebug_flag) = ( $DEBUGging ) ? '-DDEBUG' : ''; - if ($RegisteriseC) { - $cc = $CcRegd; - $s_output = ($is_hc_file || $TargetPlatform =~ /^(hppa|i386)/) ? $cc_as_o : $cc_as; - $c_flags .= " @CcRegd_flags"; - $c_flags .= ($is_hc_file) ? " @CcRegd_flags_hc" : " @CcRegd_flags_c"; - } else { - $cc = $CcUnregd; - $s_output = $cc_as; - $c_flags .= " @CcUnregd_flags"; - $c_flags .= ($is_hc_file) ? " @CcUnregd_flags_hc" : " @CcUnregd_flags_c"; - } - - # C compiler won't like the .hc extension. So we create - # a tmp .c file which #include's the needful. - open(TMP, "> $cc_help") || &tidy_up_and_die(1,"$Pgm: failed to open `$cc_help' (to write)\n"); - if ( $is_hc_file ) { - print TMP <<EOINCL; -#ifdef __STG_GCC_REGS__ -# if ! (defined(MAIN_REG_MAP) || defined(MARK_REG_MAP) || defined(SCAN_REG_MAP) || defined(SCAV_REG_MAP) || defined(FLUSH_REG_MAP)) -# define MAIN_REG_MAP -# endif -#endif -#include "stgdefs.h" -EOINCL - # user may have asked for #includes to be injected... - print TMP @CcInjects if $#CcInjects >= 0; - } - # heave in the consistency info - print TMP "static char ghc_cc_ID[] = \"\@(#)cc $ifile\t$Cc_major_version.$Cc_minor_version,$Cc_consist_options\";\n"; + $to_do = "echo '#line 1 \"$in_lit2pgm\"' > $hscpp_hsc && ". + "$HsCpp $Verbose $genSPECS_flag @HsCpp_flags -D__HASKELL1__=$Haskell1Version -D__GLASGOW_HASKELL__=$GhcVersionInfo $includes $lit2pgm_hscpp >> $hscpp_hsc"; + @Files_to_tidy = ( $hscpp_hsc ); + &run_something($to_do, 'Haskellised C pre-processor'); + } +} +\end{code} - # and #include the real source - print TMP "#include \"$hsc_cc\"\n"; - close(TMP) || &tidy_up_and_die(1,"Failed writing to $cc_help\n"); +\begin{code} +sub runHsc { + local($ifile_root, $hsc_out, $hsc_hi, $going_interactive) = @_; - 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 )"; - # note: __GLASGOW_HASKELL__ is pointedly *not* #defined at the C level. - if ( $Only_preprocess_C ) { # HACK ALERT! - $to_do =~ s/ -S\b//g; - } - @Files_to_tidy = ( $cc_help, $cc_help_s, $s_output ); - $PostprocessCcOutput = 1; # hack, dear hack... - &run_something($to_do, 'C compiler'); - $PostprocessCcOutput = 0; - unlink($cc_help, $cc_help_s); - - if ( ($RegisteriseC && $is_hc_file) - || $Dump_asm_insn_counts - || $Dump_asm_globals_info ) { - # dynamically load assembler-fiddling code, which we are about to use - local($target) = 'oops'; - $target = '-alpha' if $TargetPlatform =~ /^alpha-/; - $target = '-hppa' if $TargetPlatform =~ /^hppa/; - $target = '' if $TargetPlatform =~ /^i386-/; - $target = '-m68k' if $TargetPlatform =~ /^m68k-/; - $target = '-mips' if $TargetPlatform =~ /^mips-/; - $target = '' if $TargetPlatform =~ /^powerpc-/; - $target = '-solaris' if $TargetPlatform =~ /^sparc-sun-solaris2/; - $target = '-sparc' if $TargetPlatform =~ /^sparc-sun-sunos4/; - - $target ne 'oops' - || &tidy_up_and_die(1,"$Pgm: panic: can't decipher $TargetPlatform!\n"); - require("ghc-asm$target.prl") - || &tidy_up_and_die(1,"$Pgm: panic: can't load ghc-asm$target.prl!\n"); - } + # prepend comma to HsP flags (so hsc can tell them apart...) + foreach $a ( @HsP_flags ) { $a = ",$a" unless $a =~ /^,/; } - if ( $Dump_raw_asm ) { # to stderr, before mangling - local($to_pr) = ($RegisteriseC) ? $cc_as_o : $cc_as ; - print STDERR `cat $to_pr`; - } + &makeHiMap() unless $HiMapDone; + push(@HsC_flags, "-himap=$HiMapFile"); - if ($RegisteriseC) { - if ($is_hc_file) { - # post-process the assembler [.hc files only] - &mangle_asm($cc_as_o, $cc_as); - - } elsif ($TargetPlatform =~ /^hppa/) { - # minor mangling of non-threaded files for hp-pa only - require('ghc-asm-hppa.prl') - || &tidy_up_and_die(1,"$Pgm: panic: can't load ghc-asm-hppa.prl!\n"); - &mini_mangle_asm($cc_as_o, $cc_as); - - } elsif ($TargetPlatform =~ /^i386/) { - # extremely-minor OFFENSIVE mangling of non-threaded just one file - require('ghc-asm.prl') - || &tidy_up_and_die(1,"$Pgm: panic: can't load ghc-asm.prl!\n"); - &mini_mangle_asm($cc_as_o, $cc_as); - } - } + # here, we may produce .hc/.s and/or .hi files + local($output) = ''; + @Files_to_tidy = (); - # collect interesting (static-use) info - &dump_asm_insn_counts($cc_as) if $Dump_asm_insn_counts; - &dump_asm_globals_info($cc_as) if $Dump_asm_globals_info; + if ( $going_interactive ) { + # don't need .hi unless going to show it on stdout: + $ProduceHi = '-nohifile=' if ! $HiOnStdout; + $do_cc = 0; $do_as = 0; $Do_lnkr = 0; # and we won't go any further... + } - # save a copy of the .s file, even if we are carrying on... - if ($do_as && $Keep_s_file_too) { - local($to_do) = "$(RM) $ifile_root.s; cp $cc_as $ifile_root.s"; - &run_something($to_do, 'Saving copy of .s file'); - } + # set up for producing output/.hi; note that flag twiddling + # may mean that nothing will actually be produced: + $output = "$ProduceHi$hsc_hi $HscOut$hsc_out"; + @Files_to_tidy = ( $hsc_hi, $hsc_out ); + + # if we're compiling foo.hs, we want the GC stats to end up in foo.stat + if ( $CollectingGCstats ) { + push(@HsC_rts_flags, "-S$ifile_root.stat"); + push(@Files_to_tidy, "$ifile_root.stat"); } - if ($do_as) { - # if we're splitting .o files... - if ( $SplitObjFiles ) { - &split_asm_file ( $cc_as ); - } + if ( $CollectGhcTimings ) { # assume $RTS_style eq 'ghc' + # emit nofibbish time/bytes-alloc stats to stderr; + # see later .stat file post-processing + push(@HsC_rts_flags, "-s$Tmp_prefix.stat"); + push(@Files_to_tidy, "$Tmp_prefix.stat"); + } - local($asmblr) = ( $As ) ? $As : ($RegisteriseC ? $CcRegd : $CcUnregd ); + local($dump) = ''; + if ($Specific_dump_file ne '') { + $dump = "2>> $Specific_dump_file"; + $Using_dump_file = 1; + } - if ( ! $SplitObjFiles ) { - local($to_do) = "$asmblr -o $as_out -c @As_flags $cc_as"; - @Files_to_tidy = ( $as_out ); - &run_something($to_do, 'Unix assembler'); + local($to_do); + $to_do = "$HsC @HsP_flags ,$hscpp_hsc $dump @HsC_flags $CoreLint $Verbose $output +RTS @HsC_rts_flags"; + &run_something($to_do, 'Haskell compiler'); + + # finish business w/ nofibbish time/bytes-alloc stats + &process_ghc_timings() if $CollectGhcTimings; + + # if non-interactive, heave in the consistency info at the end + # NB: pretty hackish (depends on how $output is set) + if ( ! $going_interactive ) { + if ( $HscOut eq '-C=' ) { + $to_do = "echo 'static char ghc_hsc_ID[] = \"\@(#)hsc $ifile\t$HsC_major_version.$HsC_minor_version,$HsC_consist_options\";' >> $hsc_out"; + + } elsif ( $HscOut eq '-S=' ) { + local($consist) = "hsc.$ifile.$HsC_major_version.$HsC_minor_version.$HsC_consist_options"; + $consist =~ s/,/./g; + $consist =~ s/\//./g; + $consist =~ s/-/_/g; + $consist =~ s/[^A-Za-z0-9_.]/ZZ/g; # ToDo: properly? + $to_do = "echo '\n\t.text\n$consist:' >> $hsc_out"; + } + &run_something($to_do, 'Pin on Haskell consistency info'); + } +} +\end{code} - } else { # more complicated split-ification... +Use \tr{@Import_dir} and \tr{@SysImport_dir} to make a tmp file +of (module-name, pathname) pairs, one per line, separated by a space. +\begin{code} +%HiMap = (); +$HiMapDone = 0; +$HiMapFile = ''; - # must assemble files $Tmp_prefix__[1 .. $NoOfSplitFiles].s +sub makeHiMap { - for ($f = 1; $f <= $NoOfSplitFiles; $f++ ) { - local($split_out) = &odir_ify("${ifile_root}__${f}${Osuffix}"); - local($to_do) = "$asmblr -o $split_out -c @As_flags ${Tmp_prefix}__${f}.s"; - @Files_to_tidy = ( $split_out ); + # collect in %HiMap; write later; also used elsewhere in driver - &run_something($to_do, 'Unix assembler'); + local($mod, $path, $d, $e); + + foreach $d ( @Import_dir ) { + opendir(DIR, $d) || &tidy_up_and_die(1,"$Pgm: error when reading directory: $d\n"); + local(@entry) = readdir(DIR); + foreach $e ( @entry ) { + next unless $e =~ /([A-Z][A-Za-z0-9_]*)\.$HiSuffix$/o; + $mod = $1; + $path = "$d/$e"; + $path =~ s,^\./,,; + + if ( ! defined($HiMap{$mod}) ) { + $HiMap{$mod} = $path; + } else { + &already_mapped_err($mod, $HiMap{$mod}, $path); } } + closedir(DIR); # || &tidy_up_and_die(1,"$Pgm: error when closing directory: $d\n"); } -} # end of ProcessInputFile + + foreach $d ( @SysImport_dir ) { + opendir(DIR, $d) || &tidy_up_and_die(1,"$Pgm: error when reading directory: $d\n"); + local(@entry) = readdir(DIR); + foreach $e ( @entry ) { + next unless $e =~ /([A-Z][A-Za-z0-9_]*)\.$SysHiSuffix$/o; + next if $NoImplicitPrelude && $e =~ /Prelude\.$SysHiSuffix$/o; + + $mod = $1; + $path = "$d/$e"; + $path =~ s,^\./,,; + + if ( ! defined($HiMap{$mod}) ) { + $HiMap{$mod} = $path; + } elsif ( $mod ne 'Main' ) { # saves useless warnings... + &already_mapped_err($mod, $HiMap{$mod}, $path); + } + } + closedir(DIR); # || &tidy_up_and_die(1,"$Pgm: error when closing directory: $d\n"); + } + + $HiMapFile = "$Tmp_prefix.himap"; + unlink($HiMapFile); + open(HIMAP, "> $HiMapFile") || &tidy_up_and_die(1,"$Pgm: can't open $HiMapFile\n"); + foreach $d (keys %HiMap) { + print HIMAP $d, ' ', $HiMap{$d}, "\n"; + } + close(HIMAP) || &tidy_up_and_die(1,"$Pgm: error when closing $HiMapFile\n"); + + $HiMapDone = 1; +} + +sub already_mapped_err { + local($mod, $mapped_to, $path) = @_; + + # OK, it isn't really an error if $mapped_to and $path turn + # out to be the same thing. + ($m_dev,$m_ino,$m_mode,$m_nlink,$m_uid,$m_gid,$m_rdev,$m_size, + $m_atime,$m_mtime,$m_ctime,$m_blksize,$m_blocks) = stat($mapped_to); + ($p_dev,$p_ino,$p_mode,$p_nlink,$p_uid,$p_gid,$p_rdev,$p_size, + $p_atime,$p_mtime,$p_ctime,$p_blksize,$p_blocks) = stat($path); + + return if $m_ino == $p_ino; # same inode number + + print STDERR "$Pgm: module $mod already mapped to $mapped_to (inode $m_ino)"; + print STDERR ";\n\tignoring: $path (inode $p_ino)\n"; +} \end{code} %************************************************************************ @@ -2520,14 +2329,157 @@ EOINCL %************************************************************************ \begin{code} +sub osuf_ify { + local($ofile,$def_suffix) = @_; + + return(($Osuffix eq '') ? "$ofile.$def_suffix" : "$ofile.$Osuffix" ); +} + sub odir_ify { - local($orig_file) = @_; + local($orig_file, $def_suffix) = @_; if ($Specific_output_dir eq '') { # do nothing - return($orig_file); + &osuf_ify($orig_file, $def_suffix); } else { local ($orig_file_only); ($orig_file_only = $orig_file) =~ s|.*/||; - return("$Specific_output_dir/$orig_file_only"); + &osuf_ify("$Specific_output_dir/$orig_file_only",$def_suffix); + } +} +\end{code} + +\begin{code} +sub runGcc { + local($is_hc_file, $hsc_out, $cc_as_o) = @_; + + local($includes) = '-I' . join(' -I', @Include_dir); + local($cc); + local($s_output); + local($c_flags) = "@CcBoth_flags"; + local($ddebug_flag) = ( $DEBUGging ) ? '-DDEBUG' : ''; + + # "input" files to use that are not in some weird directory; + # to help C compilers grok .hc files [ToDo: de-hackify] + local($cc_help) = "ghc$$.c"; + local($cc_help_s) = "ghc$$.s"; + + $cc = $CcRegd; + $s_output = ($is_hc_file || $TargetPlatform =~ /^(hppa|i386)/) ? $cc_as_o : $cc_as; + $c_flags .= " @CcRegd_flags"; + $c_flags .= ($is_hc_file) ? " @CcRegd_flags_hc" : " @CcRegd_flags_c"; + + # C compiler won't like the .hc extension. So we create + # a tmp .c file which #include's the needful. + open(TMP, "> $cc_help") || &tidy_up_and_die(1,"$Pgm: failed to open `$cc_help' (to write)\n"); + if ( $is_hc_file ) { + print TMP <<EOINCL; +#ifdef __STG_GCC_REGS__ +# if ! (defined(MAIN_REG_MAP) || defined(MARK_REG_MAP) || defined(SCAN_REG_MAP) || defined(SCAV_REG_MAP) || defined(FLUSH_REG_MAP)) +# define MAIN_REG_MAP +# endif +#endif +#include "stgdefs.h" +EOINCL + # user may have asked for #includes to be injected... + print TMP @CcInjects if $#CcInjects >= 0; + } + # heave in the consistency info + print TMP "static char ghc_cc_ID[] = \"\@(#)cc $ifile\t$Cc_major_version.$Cc_minor_version,$Cc_consist_options\";\n"; + + # and #include the real source + print TMP "#include \"$hsc_out\"\n"; + close(TMP) || &tidy_up_and_die(1,"Failed writing to $cc_help\n"); + + local($to_do) = "$cc $Verbose $ddebug_flag $c_flags @Cpp_define -D__HASKELL1__=$Haskell1Version $includes $cc_help > $Tmp_prefix.ccout 2>&1 && ( if [ $cc_help_s != $s_output ] ; then mv $cc_help_s $s_output ; else exit 0 ; fi )"; + # note: __GLASGOW_HASKELL__ is pointedly *not* #defined at the C level. + if ( $Only_preprocess_C ) { # HACK ALERT! + $to_do =~ s/ -S\b//g; + } + @Files_to_tidy = ( $cc_help, $cc_help_s, $s_output ); + $PostprocessCcOutput = 1; # hack, dear hack... + &run_something($to_do, 'C compiler'); + $PostprocessCcOutput = 0; + unlink($cc_help, $cc_help_s); +} +\end{code} + +\begin{code} +sub runMangler { + local($is_hc_file, $cc_as_o, $cc_as, $ifile_root) = @_; + + if ( $is_hc_file ) { + # dynamically load assembler-fiddling code, which we are about to use: + require('ghc-asm.prl') + || &tidy_up_and_die(1,"$Pgm: panic: can't load ghc-asm.prl!\n"); + } + + print STDERR `cat $cc_as_o` if $Dump_raw_asm; # to stderr, before mangling + + if ($is_hc_file) { + # post-process the assembler [.hc files only] + &mangle_asm($cc_as_o, $cc_as); + +#OLD: for sanity: + local($target) = 'oops'; + $target = '-alpha' if $TargetPlatform =~ /^alpha-/; + $target = '-hppa' if $TargetPlatform =~ /^hppa/; + $target = '' if $TargetPlatform =~ /^i386-/; + $target = '-m68k' if $TargetPlatform =~ /^m68k-/; + $target = '-mips' if $TargetPlatform =~ /^mips-/; + $target = '' if $TargetPlatform =~ /^powerpc-/; + $target = '-solaris' if $TargetPlatform =~ /^sparc-sun-solaris2/; + $target = '-sparc' if $TargetPlatform =~ /^sparc-sun-sunos4/; + + if ( $target ne '' ) { + require("ghc-asm$target.prl") + || &tidy_up_and_die(1,"$Pgm: panic: can't load ghc-asm$target.prl!\n"); + &mangle_asm($cc_as_o, "$cc_as-2"); # the OLD one! + &run_something("$Cmp -s $cc_as-2 $cc_as || $Diff $cc_as-2 $cc_as 1>&2 || exit 0", + "Diff'ing old and new mangled .s files"); # NB: to stderr + } + + } elsif ($TargetPlatform =~ /^hppa/) { + # minor mangling of non-threaded files for hp-pa only + require('ghc-asm.prl') + || &tidy_up_and_die(1,"$Pgm: panic: can't load ghc-asm-hppa.prl!\n"); + &mini_mangle_asm_hppa($cc_as_o, $cc_as); + + } elsif ($TargetPlatform =~ /^i386/) { + # extremely-minor OFFENSIVE mangling of non-threaded just one file + require('ghc-asm.prl') + || &tidy_up_and_die(1,"$Pgm: panic: can't load ghc-asm.prl!\n"); + &mini_mangle_asm_i386($cc_as_o, $cc_as); + } + + # save a copy of the .s file, even if we are carrying on... + if ($do_as && $Keep_s_file_too) { + local($to_do) = "$Rm $ifile_root.s; $Cp $cc_as $ifile_root.s"; + &run_something($to_do, 'Saving copy of .s file'); + } +} +\end{code} + +\begin{code} +sub runAs { + local($as_out, $ifile_root) = @_; + + local($asmblr) = ( $As ) ? $As : $CcRegd; + + if ( ! $SplitObjFiles ) { + local($to_do) = "$asmblr -o $as_out -c @As_flags $cc_as"; + @Files_to_tidy = ( $as_out ); + &run_something($to_do, 'Unix assembler'); + + } else { # more complicated split-ification... + + # must assemble files $Tmp_prefix__[1 .. $NoOfSplitFiles].s + + for ($f = 1; $f <= $NoOfSplitFiles; $f++ ) { + local($split_out) = &odir_ify("${ifile_root}__${f}",'o'); + local($to_do) = "$asmblr -o $split_out -c @As_flags ${Tmp_prefix}__${f}.s"; + @Files_to_tidy = ( $split_out ); + + &run_something($to_do, 'Unix assembler'); + } } } \end{code} @@ -2592,60 +2544,6 @@ sub run_something { %************************************************************************ %* * -\subsection[Driver-demangle-C-and-hi]{@extract_c_and_hi_files@: Unscramble Haskell-compiler output} -%* * -%************************************************************************ - -Update interface if the tmp one is newer... -We first have to fish the module name out of the interface. -\begin{code} -sub diff_hi_file { - local($tmp_hi_file, $hi_file) = @_; - local($if_modulename) = ''; - - # extract the module name - - open(TMP, "< $tmp_hi_file")|| &tidy_up_and_die(1,"$Pgm: failed to open `$tmp_hi_file' (to read)\n"); - while (<TMP>) { - if ( /^interface ([A-Za-z0-9'_]+) / ) { - $if_modulename = $1; - } - } - close(TMP) || &tidy_up_and_die(1,"Failed reading from $tmp_hi_file\n"); - &tidy_up_and_die(1,"No module name in $tmp_hi_file\n") - if ! $if_modulename; - - #compare/diff with old one - - if ($hi_file eq '-') { - &run_something("cat $tmp_hi_file", "copy interface to stdout"); - - } else { - if ($Specific_hi_file eq '' && $if_modulename ne '') { - if ( $hi_file =~ /\// ) { - $hi_file =~ s/\/[^\/]+$//; - $hi_file .= "/$if_modulename$HiSuffix"; - } else { - $hi_file = "$if_modulename$HiSuffix"; - } - print STDERR "interface really going into: $hi_file\n" if $Verbose; - } - - if ($HiDiff_flag && -f $hi_file) { - local($diffcmd) = '$(CONTEXT_DIFF)'; - - &run_something("cmp -s $tmp_hi_file $hi_file || $(CONTEXT_DIFF) $hi_file $tmp_hi_file 1>&2 || exit 0", - "Diff'ing old and new $HiSuffix files"); # NB: to stderr - } - - &run_something("cmp -s $tmp_hi_file $hi_file || ( $(RM) $hi_file && $(CP) $tmp_hi_file $hi_file )", - "Comparing old and new $HiSuffix files"); - } -} -\end{code} - -%************************************************************************ -%* * \subsection[Driver-ghctiming]{Emit nofibbish GHC timings} %* * %************************************************************************ @@ -2728,7 +2626,7 @@ sub process_ghc_timings { \begin{code} sub tidy_up { - local($to_do) = "\n$(RM) $Tmp_prefix*"; + local($to_do) = "\n$Rm $Tmp_prefix*"; if ( $Tmp_prefix !~ /^\s*$/ ) { print STDERR "$to_do\n" if $Verbose; system($to_do); @@ -2812,3 +2710,4 @@ sub add_Hsc_flags { } } \end{code} + |