X-Git-Url: http://git.megacz.com/?a=blobdiff_plain;f=ghc%2Fdriver%2Fghc.lprl;h=86987b76bffc455ea86d049249059b48f36d57bc;hb=ac9a538680b0b647d891f7409f6267d2b762d19d;hp=36732e650a633d4a88b4e048b75ffde8c858d7bd;hpb=2a3a552c0aa2302deaf6fadd5badbbb0d193b3b1;p=ghc-hetmet.git diff --git a/ghc/driver/ghc.lprl b/ghc/driver/ghc.lprl index 36732e6..86987b7 100644 --- a/ghc/driver/ghc.lprl +++ b/ghc/driver/ghc.lprl @@ -1,4 +1,3 @@ -% % (c) The GRASP/AQUA Project, Glasgow University, 1992-1997 % @@ -46,8 +45,8 @@ to stdout or stderr, however). The phase at which to STOP processing is determined by a command-line option: + -E stop after generating preprocessed, de-litted Haskell (used in conjunction with -cpp) -C stop after generating C (.hc output) - -E stop after generating preprocessed C (.i output) -S stop after generating assembler (.s output) -c stop after generating object files (.o output) @@ -64,9 +63,9 @@ Other commonly-used options are: -M Output the Makefile rules recording the dependencies of a list of Haskell files. - (ghc driver just calls upon the help of a - compatible mkdependHS script to do the - actual processing) + (ghc driver script calls upon the help of a + compatible mkdependHS script to do the actual + processing) The User's Guide has more information about GHC's *many* options. @@ -99,7 +98,9 @@ INSTALLING HOSTPLATFORM TARGETPLATFORM -PROJECTNAME PROJECTVERSION PROJECTPATCHLEVEL +ProjectName ProjectVersion ProjectVersionInt ProjectPatchLevel + +HscMajorVersion HscMinorVersion CcMajorVersion CcMinorVersion TOP_PWD @@ -138,7 +139,6 @@ $InstLibDirGhc = "${libdir}"; # $InstLibExecDirGhc = "${libexecdir}"; $InstDataDirGhc = "${datadir}"; -$InstSysLibDir = ( $INSTALLING ) ? "${InstLibDirGhc}/hslibs" : "$TopPwd/hslibs"; $Status = 0; # just used for exit() status $Verbose = ''; @@ -191,11 +191,10 @@ $Cmp = 'cmp'; $Time = ''; $HsCpp = # but this is re-set to "cat" (after options) if -cpp not seen - ( $INSTALLING ) ? "$InstLibexecDirGhc/hscpp" + ( $INSTALLING ) ? "$InstLibExecDirGhc/hscpp" : "$TopPwd/${CURRENT_DIR}/${GHC_HSCPP}"; @HsCpp_flags = (); -$genSPECS_flag = ''; # See ../utils/hscpp/hscpp.prl $HsC = ( $INSTALLING ) ? "$InstLibExecDirGhc/hsc" : "$TopPwd/${CURRENT_DIR}/${GHC_HSC}"; @@ -222,18 +221,17 @@ These are the default values, which may be changed by user flags. \begin{code} sub setupOptFlags { - $Oopt_UnfoldingUseThreshold = '-fsimpl-uf-use-threshold3'; $Oopt_MaxSimplifierIterations = '-fmax-simplifier-iterations4'; $Oopt_PedanticBottoms = '-fpedantic-bottoms'; # ON by default $Oopt_MonadEtaExpansion = ''; $Oopt_FinalStgProfilingMassage = ''; $Oopt_StgStats = ''; - $Oopt_SpecialiseUnboxed = ''; - $Oopt_DoSpecialise = ''; # ToDo:LATER: '-fspecialise'; + $Oopt_DoSpecialise = '-fspecialise'; $Oopt_FoldrBuild = 0; # *Off* by default! $Oopt_FB_Support = ''; # was '-fdo-arity-expand'; # $Oopt_FoldrBuildWW = 0; # Off by default $Oopt_FoldrBuildInline = ''; # was '-fdo-inline-foldr-build'; + $Oopt_ShowSimplifierProgress = ''; } # end of setupOptFlags # Assign defaults to these right away. @@ -241,9 +239,13 @@ sub setupOptFlags { \end{code} Things to do with C compilers/etc: + +(added -Wimplicit: implicit prototypes cause very hard-to-find +problems, so I'm turing on the warnings -- SDM 4/5/98) + \begin{code} $CcRegd = $GHC_OPT_HILEV_ASM; -@CcBoth_flags = ('-S'); # flags for *any* C compilation +@CcBoth_flags = ('-S','-Wimplicit'); # flags for *any* C compilation @CcInjects = (); # GCC flags: @@ -251,22 +253,47 @@ $CcRegd = $GHC_OPT_HILEV_ASM; # 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 = (); +@CcRegd_flags_c = (); @CcRegd_flags_hc = (); -$As = ''; # "assembler" is normally GCC -@As_flags = (); +$As = ''; # "assembler" is normally GCC +@As_flags = (); -$Lnkr = ''; # "linker" is normally GCC -@Ld_flags = (); +$Lnkr = ''; # "linker" is normally GCC +@Ld_flags = (); # 'nm' is used for consistency checking (ToDo: mk-world-ify) # ToDo: check the OS or something ("alpha" is surely not the crucial question) $Nm = ($TargetPlatform =~ /^alpha-/) ? 'nm -B' : 'nm'; \end{code} +Warning packages that are controlled by -W and -Wall. The 'standard' +warnings that you get all the time are + + -fwarn-overlapping-patterns + -fwarn-missing-methods + -fwarn-duplicate-exports + +these are turned off by -Wnot. + +\begin{code} +@StandardWarnings = ('-fwarn-overlapping-patterns', + '-fwarn-missing-methods', + '-fwarn-duplicate-exports'); +@MinusWOpts = (@StandardWarnings, + '-fwarn-incomplete-patterns', + '-fwarn-unused-binds', + '-fwarn-unused-imports'); +@MinusWallOpts = (@MinusWOpts, + '-fwarn-unused-matches', + '-fwarn-type-defaults', + '-fwarn-name-shadowing', + '-fwarn-missing-signatures'); +\end{code} + What options \tr{-user-setup-a} turn into (user-defined ``packages'' + of options). Note that a particular user-setup implies a particular Prelude ({\em including} its interface file(s)). \begin{code} @@ -277,14 +304,8 @@ $BuildTag = ''; # default is sequential build w/ Appel-style GC '_p', "$WAY_p_NAME", '_t', "$WAY_t_NAME", '_u', "$WAY_u_NAME", - '_mc', "$WAY_mc_NAME", - '_mr', "$WAY_mr_NAME", - '_mt', "$WAY_mt_NAME", '_mp', "$WAY_mp_NAME", '_mg', "$WAY_mg_NAME", - '_2s', "$WAY_2s_NAME", - '_1s', "$WAY_1s_NAME", - '_du', "$WAY_du_NAME", # system ways end '_a', "$WAY_a_NAME", '_b', "$WAY_b_NAME", @@ -330,83 +351,8 @@ $BuildTag = ''; # default is sequential build w/ Appel-style GC '_p', "$WAY_p_HC_OPTS", '_t', "$WAY_t_HC_OPTS", '_u', "$WAY_u_HC_OPTS", - '_mc', "$WAY_mc_HC_OPTS", - '_mr', "$WAY_mr_HC_OPTS", - '_mt', "$WAY_mt_HC_OPTS", '_mp', "$WAY_mp_HC_OPTS", - '_mg', "$WAY_mg_HC_OPTS", - '_2s', "$WAY_2s_HC_OPTS", - '_1s', "$WAY_1s_HC_OPTS", - '_du', "$WAY_B_HC_OPTS" ); - -# per-build code fragments which are eval'd -#%EvaldSetupOpts = ('', '', # this one must *not* be set! - -# # profiled sequential -# '_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\');', - -##OLD: # unregisterized (ToDo????) -## '_u', '', - -# # concurrent -# '_mc', '$StkChkByPageFaultOK = 0; -# push(@HsC_flags, \'-fconcurrent\'); -# push(@HsCpp_flags,\'-D__CONCURRENT_HASKELL__\', \'-DCONCURRENT\'); -# push(@Cpp_define, \'-D__CONCURRENT_HASKELL__\', \'-DCONCURRENT\');', - -# # profiled concurrent -# '_mr', '$StkChkByPageFaultOK = 0; -# push(@HsC_flags, \'-fconcurrent\', \'-fscc-profiling\'); -# push(@HsCpp_flags,\'-D__CONCURRENT_HASKELL__\', \'-DCONCURRENT\'); -# push(@Cpp_define, \'-D__CONCURRENT_HASKELL__\', \'-DCONCURRENT\', \'-DPROFILING\');', - -# # ticky-ticky concurrent -# '_mt', '$StkChkByPageFaultOK = 0; -# push(@HsC_flags, \'-fconcurrent\', \'-fticky-ticky\'); -# push(@HsCpp_flags,\'-D__CONCURRENT_HASKELL__\', \'-DCONCURRENT\'); -# push(@Cpp_define, \'-D__CONCURRENT_HASKELL__\', \'-DCONCURRENT\', \'-DTICKY_TICKY\');', - -# # parallel -# '_mp', '$StkChkByPageFaultOK = 0; -# push(@HsC_flags, \'-fconcurrent\'); -# push(@HsCpp_flags,\'-D__PARALLEL_HASKELL__\', \'-DPAR\'); -# push(@Cpp_define, \'-D__CONCURRENT_HASKELL__\', \'-DCONCURRENT\', \'-DPAR\');', - -# # GranSim -# '_mg', '$StkChkByPageFaultOK = 0; -# push(@HsC_flags, \'-fconcurrent\', \'-fgransim\'); -# push(@HsCpp_flags,\'-D__GRANSIM__\', \'-DGRAN\'); -# push(@Cpp_define, \'-D__CONCURRENT_HASKELL__\', \'-DCONCURRENT\', \'-DGRAN\');', - -# '_2s', 'push (@CcBoth_flags, \'-DGC2s\');', -# '_1s', 'push (@CcBoth_flags, \'-DGC1s\');', -# '_du', 'push (@CcBoth_flags, \'-DGCdu\');', - -# '_a', '', # these user-way guys should not be set! -# '_b', '', -# '_c', '', -# '_d', '', -# '_e', '', -# '_f', '', -# '_g', '', -# '_h', '', -# '_i', '', -# '_j', '', -# '_k', '', -# '_l', '', -# '_m', '', -# '_n', '', -# '_o', '', -# '_A', '', -# '_B', '' ); + '_mg', "$WAY_mg_HC_OPTS"); \end{code} @@ -417,21 +363,27 @@ require special handling. @Import_dir = ('.'); #-i things @Include_dir = ('.'); #-I things; other default(s) stuck on AFTER option processing -# where to look for interface files (system hi's, i.e., prelude and hslibs) +# where to look for interface files (system hi's, i.e., prelude and syslibs) @SysImport_dir = ( $INSTALLING ) - ? ( "$InstLibDirGhc/imports" ) - : ( "$TopPwd/$CURRENT_DIR/$GHC_LIB_DIR/required" - , "$TopPwd/$CURRENT_DIR/$GHC_LIB_DIR/ghc" - , "$TopPwd/$CURRENT_DIR/$GHC_LIB_DIR/glaExts" - , "$TopPwd/$CURRENT_DIR/$GHC_LIB_DIR/concurrent" ); + ? ( "$InstLibDirGhc/imports/std" ) + : ( "$TopPwd/$CURRENT_DIR/$GHC_LIB_DIR/std" ); # We need to look in ghc/ and glaExts/ when searching for implicitly needed .hi files, but # we should really *not* look there for explicitly imported modules. -$GhcVersionInfo = int ($PROJECTVERSION * 100); -$Haskell1Version = 4; # i.e., Haskell 1.4 +$Haskell1Version = 5; # i.e., Haskell 1.4 @Cpp_define = (); +# Cpp symbols defined when we're processing Haskell source. + +@HsSourceCppOpts = + ( "-D__HASKELL1__=$Haskell1Version" + , "-D__GLASGOW_HASKELL__=$ProjectVersionInt" + , "-D__HASKELL98__" + # not yet -- SDM + # , "-D__CONCURRENT_HASKELL__" + ); + @UserLibrary_dir= (); #-L things;... @UserLibrary = (); #-l things asked for by the user @@ -439,22 +391,23 @@ $Haskell1Version = 4; # i.e., Haskell 1.4 ? $InstLibDirGhc : ( "$TopPwd/$CURRENT_DIR/$GHC_RUNTIME_DIR" , "$TopPwd/$CURRENT_DIR/$GHC_RUNTIME_DIR/gmp" - , "$TopPwd/$CURRENT_DIR/$GHC_LIB_DIR" - , "$TopPwd/$CURRENT_DIR/$GHC_LIB_DIR/cbits" + , "$TopPwd/$CURRENT_DIR/$GHC_LIB_DIR/std" + , "$TopPwd/$CURRENT_DIR/$GHC_LIB_DIR/std/cbits" ) ); @SysLibrary = (); # will be built up as we go along $TopClosureFile # defaults to 1.2 one; will be mangled later - = ( $INSTALLING) ? "$InstLibDirGhc/TopClosureXXXX.o" - : "$TopPwd/$CURRENT_DIR/$GHC_RUNTIME_DIR/main/TopClosureXXXX.o"; + = ''; +# ( $INSTALLING) ? "$InstLibDirGhc/TopClosureXXXX.o" +# : "$TopPwd/$CURRENT_DIR/$GHC_RUNTIME_DIR/main/TopClosureXXXX.o"; # make depend for Haskell $MkDependHS = ( $INSTALLING ) ? "$InstBinDirGhc/mkdependHS" : "$TopPwd/$CURRENT_DIR/$GHC_UTILS_DIR/mkdependHS/mkdependHS"; # Fill in later -@MkDependHS_flags = ( ); +@MkDependHS_flags = (); # do_link flag should not be reset while rescanning the cmd-line. $Do_lnkr = 1; @@ -487,14 +440,6 @@ $StolenX86Regs = 4; # **HACK*** of the very worst sort $CoreLint = ''; $StgLint = ''; -@CcBoth_flags = ('-S'); # flags for *any* C compilation -@CcInjects = (); - -# 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 = (); - @Import_dir = ('.'); #-i things @Include_dir = ('.'); #-I things; other default(s) stuck on AFTER option processing @@ -512,18 +457,21 @@ Here are the initial defaults applied to all files: \begin{code} $Cpp_flag_set = 0; # (hack) $Only_preprocess_C = 0; # pretty hackish -$Only_generate_deps = 0; # +$Only_preprocess_hc = 0; # ditto +$Only_generate_deps = 0; # " $PostprocessCcOutput = 0; # native code-gen or via C? $HaveNativeCodeGen = $GhcWithNativeCodeGen; $HscOut = '-C='; # '-C=' ==> .hc output; '-S=' ==> .s output; '-N=' ==> neither $HscOut = '-S=' - if $HaveNativeCodeGen && $TargetPlatform =~ /^(alpha|sparc)-/; -# TEMP: disable x86 if $HaveNativeCodeGen && $TargetPlatform =~ /^(i386|alpha|sparc)-/; -$ProduceHi = '-hifile='; -$HiOnStdout = 0; -$HiDiff_flag = ''; + if $HaveNativeCodeGen && $TargetPlatform =~ /^(alpha)-/; +# TEMP: disable x86 & Sparc if $HaveNativeCodeGen && $TargetPlatform =~ /^(i386|alpha|sparc)-/; +$ProduceHi = '-hifile='; +$HiOnStdout = 0; +$HiWith = ''; +$HiDiff_flag = ''; +$Keep_HiDiffs = 0; $CollectingGCstats = 0; $CollectGhcTimings = 0; @@ -536,9 +484,7 @@ $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 $GRANing = ''; # set to g if compiling for GRAN -$StkChkByPageFaultOK = 1; # may be set to 0 (false) for some builds $Specific_hi_file = ''; # set by -ohi ; "-" for stdout $Specific_dump_file = ''; # set by -odump ; "-" for stdout $Using_dump_file = 0; @@ -554,12 +500,15 @@ $Keep_hc_file_too = 0; $Keep_s_file_too = 0; $UseGhcInternals = 0; # if 1, may use GHC* modules $SplitObjFiles = 0; +$DoAsmMangling = 1; # on by default, off by -fno-asm-mangling $NoOfSplitFiles = 0; $Dump_parser_output = 0; $Dump_raw_asm = 0; $Dump_asm_splitting_info = 0; $NoImplicitPrelude = 0; - +# 1 => don't tell the linker to hoist in PrelMain.Main, as an +# external main is provided instead. +$NoHaskellMain=0; } # end of initDriverGlobals (Sigh) @@ -587,14 +536,14 @@ linking.) The checking is done by introducing/munging \tr{what(1)}-style strings. Anyway, here are the relevant global variables and their defaults: \begin{code} -$LinkChk = 1; # set to 0 if the link check should *not* be done +$LinkChk = 0; # 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 = 32; -$HsC_minor_version = 0; -$Cc_major_version = 36; -$Cc_minor_version = 1; +$HsC_major_version = $HscMajorVersion; +$HsC_minor_version = $HscMinorVersion; +$Cc_major_version = $CcMajorVersion; +$Cc_minor_version = $CcMinorVersion; # options: these must always agree $HsC_consist_options = ''; # we record, in this order: @@ -612,37 +561,6 @@ $Cc_consist_options = ''; # we record, in this order: Now slurp through the arguments. \begin{code} -#---------- user defined prelude --------------------------------------- - -if (grep(/^-user-prelude$/, @ARGV)) { - - # If ARGV contains -user-prelude we are compiling a piece of - # prelude for the user, probably with additional specialise pragmas - - # We strip out the -O -f and -user-prelude flags provided on - # the command line and add the ones used to compile the prelude - # ToDo: get these options from a common definition in mkworld - - # We also enable any options forced through with -user-prelude-force - - # Hey, Check out this grep statement ;-) (PS) - - @ARGV = grep((!/^-O/ && !/^-f/ && !/^-user-prelude$/) || s/^-user-prelude-force//, - @ARGV); - - unshift(@ARGV, - '-fcompiling-ghc-internals=???', # ToDo!!!! - '-O', - '-fshow-pragma-name-errs', - '-fshow-import-specs', - '-fglasgow-exts', - '-genSPECS', - '-DUSE_FOLDR_BUILD', - '-dcore-lint'); - - print STDERR "ghc: -user-prelude options:\n", "@ARGV", "\n"; -} - &initDriverGlobals(); &splitCmdLine(@ARGV); # Run through the cmd-line first time. @@ -654,7 +572,11 @@ if ( $Status == 0 && $Only_generate_deps ) { push (@MkDependHS_flags, "-o$Osuffix") if $Osuffix; push (@MkDependHS_flags, "-s$BuildTag") if $BuildTag; - local($to_do) = "$MkDependHS @MkDependHS_flags -- @Cmd_opts -- @Input_file" ; + # They're not (currently) needed, but we need to quote any -#include options + foreach (@Cmd_opts) { + s/-#include.*$/'$&'/g; + }; + local($to_do) = "$MkDependHS @MkDependHS_flags @HsSourceCppOpts -- @Cmd_opts -- @Input_file" ; &run_something($to_do, 'Haskell dependencies'); exit $Status; } @@ -758,11 +680,12 @@ sub setupOptimiseFlags { @HsC_minusNoO_flags = ( '-fsimplify', - '\(', + '[', $Oopt_FB_Support, '-ffloat-lets-exposing-whnf', '-ffloat-primops-ok', '-fcase-of-case', + '-fdo-case-elim', # '-fdo-lambda-eta-expansion', # too complicated '-freuse-con', # '-flet-to-case', # no strictness analysis, so... @@ -777,9 +700,22 @@ sub setupOptimiseFlags { # '-fsimpl-uf-use-threshold0', # '-fessential-unfoldings-only', - $Oopt_UnfoldingUseThreshold, + # + # The presence of -fclone-binds is *temporary* to work around + # the fact that the desugarer in 3.0{2.3} does generate + # bindings with identical ids, and the type checker doesn't perform + # properly cloned type substitutions. Instead, we make sure that all + # binders are cloned first time through the simplifier. + # + # Will be properly fixed in the `new compiler` I hear, at which point + # the cloning can be turned off here. + # + # Let's find out.. + #'-fclone-binds', + $Oopt_MaxSimplifierIterations, - '\)', + $Oopt_ShowSimplifierProgress, + ']', $Oopt_AddAutoSccs, # '-ffull-laziness', # removed 95/04 WDP following Andr\'e's lead @@ -792,7 +728,7 @@ sub setupOptimiseFlags { # initial simplify: mk specialiser happy: minimum effort please '-fsimplify', - '\(', + '[', $Oopt_FB_Support, '-fkeep-spec-pragma-ids', # required before specialisation @@ -807,23 +743,35 @@ sub setupOptimiseFlags { # f = E # g* = f # ...f... -# The g=f will get reverse-substituted later, but it's untidy. +# The g=f will get reverse-substituted later, but it's untidy. --SLPJ # -# '-fessential-unfoldings-only', -# '-fsimpl-uf-use-threshold0', +# SDM: Here's why it's necessary. +# +# If we unfold in the first pass before the specialiser is run +# we miss opportunities for specialisation because eg. wrappers +# have been inlined for specialisable functions. +# +# This shows up in PrelArr.lhs - the specialised instance for newArray +# calls the generic rangeSize, because rangeSize is strict and is +# replaced by its wrapper by the simplifier. + + '-fessential-unfoldings-only', + '-fsimpl-uf-use-threshold0', + + # See remark re: cloning in defn of minusnotO + '-fclone-binds', + '-fdo-case-elim', '-fmax-simplifier-iterations1', $Oopt_PedanticBottoms, - '\)', + ']', ($Oopt_DoSpecialise) ? ( - '-fspecialise-overloaded', - $Oopt_SpecialiseUnboxed, $Oopt_DoSpecialise, ) : (), - '-fsimplify', # need dependency anal after specialiser ... - '\(', # need tossing before calc-inlinings ... + '-fsimplify', # need dependency anal after specialiser ... + '[', # need tossing before calc-inlinings ... $Oopt_FB_Support, '-ffloat-lets-exposing-whnf', '-ffloat-primops-ok', @@ -835,17 +783,24 @@ sub setupOptimiseFlags { '-freuse-con', $Oopt_PedanticBottoms, $Oopt_MonadEtaExpansion, - $Oopt_UnfoldingUseThreshold, $Oopt_MaxSimplifierIterations, - '\)', - -#LATER: '-fcalc-inlinings1', -- pointless for 2.01 + $Oopt_ShowSimplifierProgress, + # + # The presence of -fclone-binds is *crucial* here as + # -ffull-laziness (which we're about to do next) floats + # bindings outwards, so we better make sure that this + # doesn't result in the floating out of bindings + # with identical uniques, i.e., -ffull-laziness needs + # to be preceeded by a simplifier pass with -fclone-binds + # set. + '-fclone-binds', + ']', # ($Oopt_FoldrBuildWW) ? ( # '-ffoldr-build-ww-anal', # '-ffoldr-build-worker-wrapper', # '-fsimplify', -# '\(', +# '[', # $Oopt_FB_Support, # '-ffloat-lets-exposing-whnf', # '-ffloat-primops-ok', @@ -857,9 +812,9 @@ sub setupOptimiseFlags { # '-freuse-con', # $Oopt_PedanticBottoms, # $Oopt_MonadEtaExpansion, -# $Oopt_UnfoldingUseThreshold, # $Oopt_MaxSimplifierIterations, -# '\)', +# $Oopt_ShowSimplifierProgress, +# ']', # ) : (), # this pass-ordering sequence was agreed by Simon and Andr\'e @@ -870,7 +825,7 @@ sub setupOptimiseFlags { '-ffoldr-build-on', # desugar list comprehensions for foldr/build '-fsimplify', - '\(', + '[', '-fignore-inline-pragma', # **** NB! '-fdo-foldr-build', # NB $Oopt_FB_Support, @@ -884,15 +839,15 @@ sub setupOptimiseFlags { '-freuse-con', $Oopt_PedanticBottoms, $Oopt_MonadEtaExpansion, - $Oopt_UnfoldingUseThreshold, $Oopt_MaxSimplifierIterations, - '\)', + $Oopt_ShowSimplifierProgress, + ']', ) : (), '-ffloat-inwards', '-fsimplify', - '\(', + '[', $Oopt_FB_Support, '-ffloat-lets-exposing-whnf', '-ffloat-primops-ok', @@ -908,14 +863,14 @@ sub setupOptimiseFlags { # but do reductions if you see them! $Oopt_PedanticBottoms, $Oopt_MonadEtaExpansion, - $Oopt_UnfoldingUseThreshold, $Oopt_MaxSimplifierIterations, - '\)', + $Oopt_ShowSimplifierProgress, + ']', '-fstrictness', '-fsimplify', - '\(', + '[', $Oopt_FB_Support, '-ffloat-lets-exposing-whnf', '-ffloat-primops-ok', @@ -928,9 +883,9 @@ sub setupOptimiseFlags { '-flet-to-case', # Aha! Only done after strictness analysis $Oopt_PedanticBottoms, $Oopt_MonadEtaExpansion, - $Oopt_UnfoldingUseThreshold, $Oopt_MaxSimplifierIterations, - '\)', + $Oopt_ShowSimplifierProgress, + ']', '-ffloat-inwards', @@ -939,12 +894,12 @@ sub setupOptimiseFlags { # ( ($OptLevel != 2) # ? '' -# : "-fliberate-case -fsimplify \\( $Oopt_FB_Support -ffloat-lets-exposing-whnf -ffloat-primops-ok -fcase-of-case -fdo-case-elim -fcase-merge -fdo-eta-reduction -fdo-lambda-eta-expansion -freuse-con -flet-to-case $Oopt_PedanticBottoms $Oopt_MonadEtaExpansion $Oopt_UnfoldingUseThreshold $Oopt_MaxSimplifierIterations \\)" ), +# : "-fliberate-case -fsimplify [ $Oopt_FB_Support -ffloat-lets-exposing-whnf -ffloat-primops-ok -fcase-of-case -fdo-case-elim -fcase-merge -fdo-eta-reduction -fdo-lambda-eta-expansion -freuse-con -flet-to-case $Oopt_PedanticBottoms $Oopt_MonadEtaExpansion $Oopt_MaxSimplifierIterations $Oopt_ShowSimplifierProgress ]" ), # Final clean-up simplification: '-fsimplify', - '\(', + '[', $Oopt_FB_Support, '-ffloat-lets-exposing-whnf', '-ffloat-primops-ok', @@ -961,16 +916,15 @@ sub setupOptimiseFlags { # but still do reductions if you see them! $Oopt_PedanticBottoms, $Oopt_MonadEtaExpansion, - $Oopt_UnfoldingUseThreshold, $Oopt_MaxSimplifierIterations, - '\)', + $Oopt_ShowSimplifierProgress, + ']', # '-fstatic-args', #LATER: '-fcalc-inlinings2', -- pointless for 2.01 # stg2stg passes - '-fupdate-analysis', '-flambda-lift', $Oopt_FinalStgProfilingMassage, $Oopt_StgStats, @@ -980,6 +934,7 @@ sub setupOptimiseFlags { # SPECIAL FLAGS for -O2 ($OptLevel == 2) ? ( + '-fupdate-analysis', # virtually useless; relegated to -O2 '-fsemi-tagging', ) : (), ); @@ -1004,12 +959,13 @@ if ( $OptLevel <= 0 ) { &add_Hsc_flags( @HsC_minusO_flags ); push(@CcBoth_flags, ($MinusO2ForC || $OptLevel == 2) ? '-O2' : '-O'); # not optional! # -O? to GCC is not optional! -O2 probably isn't worth it generally, - # but it *is* useful in compiling the garbage collectors (so said - # Patrick many moons ago...). + # but it *is* useful in compiling the garbage collector. } else { # -Ofile, then... &add_Hsc_flags( @HsC_minusO3_flags ); + push(@HsC_flags, $Oopt_FinalStgProfilingMassage) if $Oopt_FinalStgProfilingMassage; + push(@CcBoth_flags, ($MinusO2ForC) ? '-O2' : '-O'); # possibly to be elaborated... } @@ -1023,7 +979,7 @@ if ( $OptLevel <= 0 ) { %* * %************************************************************************ -Sort out @$BuildTag@, @$PROFing@, @$CONCURing@, @$PARing@, +Sort out @$BuildTag@, @$PROFing@, @$PARing@, @$GRANing@, @$TICKYing@: \begin{code} sub setupBuildFlags { @@ -1044,19 +1000,13 @@ sub setupBuildFlags { $Oopt_FinalStgProfilingMassage = '-fmassage-stg-for-profiling'; - push(@HsP_flags, (($PROFignore_scc) ? $PROFignore_scc : '-S')); + # Ignore user sccs when auto annotating, but warn when doing so. + $PROFignore_scc = '-W' if $PROFauto; - 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...) -# $SplitObjFiles = 0; # unset - #not an error: for now: $Status++; - } + push(@HsP_flags, (($PROFignore_scc) ? $PROFignore_scc : '-S')); } #if ( $BuildTag ne '' ) { # local($b) = $BuildDescr{$BuildTag}; - # 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; } @@ -1069,13 +1019,7 @@ sub setupBuildFlags { 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; } if ($TICKYing eq 't') { print STDERR "$Pgm: Can't do profiling with -ticky.\n"; exit 1; } - $BuildTag = ($CONCURing eq 'c') ? '_mr' : '_p' ; # possibly "profiled concurrent"... - - } elsif ( $CONCURing eq 'c' ) { - if ($PARing eq 'p') { print STDERR "$Pgm: Can't mix -concurrent with -parallel.\n"; exit 1; } - if ($GRANing eq 'g') { print STDERR "$Pgm: Can't mix -concurrent with -gransim.\n"; exit 1; } - $BuildTag = ($TICKYing eq 't') ? '_mt' : '_mc' ; # possibly "ticky concurrent"... - # "profiled concurrent" already acct'd for... + $BuildTag = '_p' ; } elsif ( $PARing eq 'p' ) { if ($GRANing eq 'g') { print STDERR "$Pgm: Can't mix -parallel with -gransim.\n"; exit 1; } @@ -1126,9 +1070,6 @@ Decide what the consistency-checking options are in force for this run: $Tag = "${Tag}_" if $Tag ne ''; $HiSuffix_prelude="${Tag}hi"; } - #push(@HsC_flags, "-hisuf-prelude=.${HiSuffix_prelude}"); # use appropriate Prelude .hi files - #push(@HsC_flags, "-hisuf=.${HiSuffix}"); - } # setupBuildFlags \end{code} @@ -1148,14 +1089,9 @@ Note: a few ``always apply'' flags were set at the very beginning. sub setupMachOpts { 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')); } elsif ($TargetPlatform =~ /^hppa/) { - # we know how to *mangle* asm for hppa - unshift(@CcRegd_flags, ('-D__STG_REV_TBLS__')); unshift(@CcBoth_flags, ('-static')); # # We don't put in '-mlong-calls', because it's only @@ -1170,31 +1106,16 @@ sub setupMachOpts { # (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 !~ /nextstep/; - # I do not know how to do STACK_CHECK_BY_PAGE_FAULT - # on NeXTs (my fault, not theirs), so I don't. - # CaS - # -fno-defer-pop : basically the same game as for m68k # - # -fomit-frame-pointer : *must* ; because we're stealing - # the fp (%ebp) for our register maps. *All* register - # maps (in MachRegs.lh) must steal it. + # -fomit-frame-pointer : *must* in .hc files; because we're stealing + # the fp (%ebp) for our register maps. unshift(@CcRegd_flags_hc, '-fno-defer-pop'); - unshift(@CcRegd_flags, '-fomit-frame-pointer'); + unshift(@CcRegd_flags_hc, '-fomit-frame-pointer'); unshift(@CcRegd_flags, "-DSTOLEN_X86_REGS=$StolenX86Regs"); } elsif ($TargetPlatform =~ /^m68k-/) { - # we know how to *mangle* asm for m68k - unshift (@CcRegd_flags, ('-D__STG_REV_TBLS__')); - unshift (@CcRegd_flags, ('-DSTACK_CHECK_BY_PAGE_FAULT=1')) if $StkChkByPageFaultOK && $TargetPlatform !~ /nextstep/; - # I do not know how to do STACK_CHECK_BY_PAGE_FAULT - # on NeXTs (my fault, not theirs), so I don't. - # CaS - # -fno-defer-pop : for the .hc files, we want all the pushing/ # popping of args to routines to be explicit; if we let things # be deferred 'til after an STGJUMP, imminent death is certain! @@ -1211,29 +1132,33 @@ sub setupMachOpts { # 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-|^rs6000/) { - # we know how to *mangle* asm for PowerPC -# :-( unshift(@CcRegd_flags, ('-D__STG_REV_TBLS__')); - unshift(@CcRegd_flags, ('-DSTACK_CHECK_BY_PAGE_FAULT=1')) if $StkChkByPageFaultOK; + } elsif ($TargetPlatform =~ /^powerpc-|^rs6000-/) { unshift(@CcBoth_flags, ('-static')); # always easier to start with unshift(@CcRegd_flags, ('-finhibit-size-directive')); # avoids traceback tables -# unshift(@Ld_flags, ('-Xlinker -bbigtoc -Xlinker -bnoquiet')); # if we have lots of toc entries... - unshift(@Ld_flags, ('-Xlinker -bbigtoc')); # just in case we have lots of toc entries... - } elsif ($TargetPlatform =~ /^sparc-/) { - # we know how to *mangle* asm for SPARC - unshift(@CcRegd_flags, ('-D__STG_REV_TBLS__')); - unshift(@CcRegd_flags, ('-DSTACK_CHECK_BY_PAGE_FAULT=1')) if $StkChkByPageFaultOK; - } } # end of setupMachOpts \end{code} +%************************************************************************ +%* * +\subsection{Set up for warnings} +%* * +%************************************************************************ + +Several warnings are turned on by default. These are supposed to be +the 'I'm pretty sure you've made a mistake here' kind of warnings. +The rest are turned on by the -W and -Wall options, or individually +via their -fwarn and -fno-warn flags. + +\begin{code} +sub setupWarningFlags { +&add_Hsc_flags( @StandardWarnings ); +} +\end{code} + Same unshifting magic, but for special linker flags. The configure script determines whether the object file symbol tables @@ -1247,16 +1172,39 @@ sub setupLinkOpts { unshift(@Ld_flags, (($Ld_main) ? ( '-u', "${uscore}Main_" . $Ld_main . '_closure' ) : ())); + + # things that are referenced by the RTS - make sure that we pull 'em in unshift(@Ld_flags, - ( '-u', "${uscore}PrelBase_Z91Z93_closure" # i.e., [] - ,'-u', "${uscore}PrelBase_IZh_static_info" - ,'-u', "${uscore}PrelBase_CZh_static_info" - ,'-u', "${uscore}PrelBase_False_inregs_info" - ,'-u', "${uscore}PrelBase_True_inregs_info" - ,'-u', "${uscore}STBase_SZh_static_info" - ,'-u', "${uscore}DEBUG_REGS" + ( '-u', "${uscore}PrelBase_Izh_static_info" + ,'-u', "${uscore}PrelBase_Czh_static_info" + ,'-u', "${uscore}PrelBase_Fzh_static_info" + ,'-u', "${uscore}PrelBase_Dzh_static_info" + ,'-u', "${uscore}PrelAddr_Azh_static_info" + ,'-u', "${uscore}PrelAddr_Wzh_static_info" + ,'-u', "${uscore}PrelAddr_I64zh_static_info" + ,'-u', "${uscore}PrelAddr_W64zh_static_info" + ,'-u', "${uscore}PrelStable_StablePtr_static_info" + ,'-u', "${uscore}PrelBase_Izh_con_info" + ,'-u', "${uscore}PrelBase_Czh_con_info" + ,'-u', "${uscore}PrelBase_Fzh_con_info" + ,'-u', "${uscore}PrelBase_Dzh_con_info" + ,'-u', "${uscore}PrelAddr_Azh_con_info" + ,'-u', "${uscore}PrelAddr_Wzh_con_info" + ,'-u', "${uscore}PrelAddr_I64zh_con_info" + ,'-u', "${uscore}PrelAddr_W64zh_con_info" + ,'-u', "${uscore}PrelStable_StablePtr_con_info" + ,'-u', "${uscore}PrelBase_False_static_closure" + ,'-u', "${uscore}PrelBase_True_static_closure" + ,'-u', "${uscore}PrelPack_unpackCString_closure" )); - + if (!$NoHaskellMain) { + unshift (@Ld_flags,'-u', "${uscore}PrelMain_mainIO_closure"); + } + if ($TargetPlatform =~ /^powerpc-|^rs6000-/) { + # sometimes we have lots of toc entries... + # unshift(@Ld_flags, ('-Xlinker -bbigtoc -Xlinker -bnoquiet')); + unshift(@Ld_flags, ('-Xlinker -bbigtoc')); + } } # end of setupLinkOpts @@ -1294,23 +1242,20 @@ sub setupSyslibs { $f .= $BuildTag if $f =~ /^-lHS/; } - # fiddle the TopClosure file name... - $TopClosureFile =~ s/XXXX//; - # Push library HSrts, plus boring clib bit push(@SysLibrary, "-lHSrts${BuildTag}"); - push(@SysLibrary, '-lHSclib'); + # # RTS compiled with cygwin32, uses the WinMM API # to implement the itimers, since cygwin.dll does not # support it. Only reqd. for `ways' that use itimers. # - push(@SysLibrary, '-lwinmm') if $BuildTag ne '' && $TargetPlatform eq 'i386-unknown-cygwin32'; + push(@SysLibrary, '-lwinmm') if $TargetPlatform eq 'i386-unknown-cygwin32'; # Push the pvm libraries if ($BuildTag eq '_mp') { $pvmlib = "$ENV{'PVM_ROOT'}/lib/$ENV{'PVM_ARCH'}"; - push(@SysLibrary, "-L$pvmlib", '-lpvm3', '-lgpvm3'); + push(@SysLibrary, "-L$pvmlib", '-lgpvm3', '-lpvm3'); if ( $ENV{'PVM_ARCH'} eq 'SUNMP' ) { push(@SysLibrary, '-lthread', '-lsocket', '-lnsl'); } elsif ( $ENV{'PVM_ARCH'} eq 'SUN4SOL2' ) { @@ -1319,7 +1264,16 @@ sub setupSyslibs { } # Push the GNU multi-precision arith lib; and the math library -push(@SysLibrary, '-lgmp'); + +# If this machine has GMP already installed, then we'll get the installed +# lib here, because presumably the one in the tree won't have been built. + +if ($LibGmp eq 'not-installed') { + push(@SysLibrary, "-lgmp"); +} else { + push(@SysLibrary, "-l$LibGmp"); +} + push(@SysLibrary, '-lm'); \end{code} @@ -1371,8 +1325,8 @@ if ($#Input_file < 0 && $#Link_file < 0) { @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 $_; } + print STDERR "Enter your Haskell program, end with ^D (on a line of its own):\n" if -t; + while () { print INF $_; } close(INF) || &tidy_up_and_die(1,"Failed writing to $Tmp_prefix.hs\n"); } @@ -1380,7 +1334,7 @@ if ($#Input_file < 0 && $#Link_file < 0) { Tell the world who we are, if they asked. \begin{code} -print STDERR "${PROJECTNAME}, version ${PROJECTVERSION}, patchlevel ${PROJECTPATCHLEVEL}\n" +print STDERR "${ProjectName}, version ${ProjectVersion}, patchlevel ${ProjectPatchLevel}\n" if $Verbose; \end{code} @@ -1423,8 +1377,14 @@ if ($Do_lnkr) { # for a linker, use an explicitly given one, or the going C compiler ... local($lnkr) = ( $Lnkr ) ? $Lnkr : $CcRegd; + if ( ($Specific_output_file eq '') && + ($TargetPlatform eq 'i386-unknown-cygwin32') ) { + $Specific_output_file = 'main.exe'; + print STDERR "Output file not specified, defaulting to \"main.exe\"\n"; + } + local($output) = ($Specific_output_file ne '') ? "-o $Specific_output_file" : ''; - @Files_to_tidy = ($Specific_output_file ne '') ? $Specific_output_file : 'a.out'; + @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'); @@ -1471,7 +1431,7 @@ eval 'exec perl -S \$0 \${1+"\$@"}' if \$running_under_some_shell; # =!=!=!=!=!=!=!=!=!=!=! # This script is automatically generated: DO NOT EDIT!!! -# Generated by Glasgow Haskell, version ${PROJECTVERSION} ${PROJECTPATCHLEVEL} +# Generated by Glasgow Haskell, version ${ProjectVersion} ${ProjectPatchLevel} # \$pvm_executable = '$pvm_executable'; \$pvm_executable_base = '$pvm_executable_base'; @@ -1540,6 +1500,8 @@ sub ProcessInputFile { # from input file (need to know for recomp # checking purposes) local($hifile_target);# ditto (but .hi file) + local($ofile_c_stub_target); + local($ofile_h_stub_target); \end{code} Handle the weirdity of input from stdin. @@ -1554,6 +1516,8 @@ Handle the weirdity of input from stdin. ? $Specific_hi_file : "$ifile_root.$HiSuffix"; # ToDo: odirify? # NB: may change if $ifile_root isn't module name (??) + ($ofile_c_stub_target = $ifile) =~s/\.[^\.\/]+$/_stub.c/; + ($ofile_h_stub_target = $ifile) =~s/\.[^\.\/]+$/_stub.h/; } else { $ifile = "$Tmp_prefix.hs"; # we know that's where we put the input $ifile_root = '_stdin'; @@ -1593,7 +1557,7 @@ Again, we'll do the post-recompilation-checker parts of this later. local($is_hc_file) = 1; #Is the C code .hc or .c? Assume .hc for now # OK, let's strip off some literate junk.. - if ($ifile =~ /\.lhs$/) { + if ($do_lit2pgm) { &runLit2pgm($in_lit2pgm, $lit2pgm_hscpp) } else { $lit2pgm_hscpp = $ifile; @@ -1604,7 +1568,8 @@ Again, we'll do the post-recompilation-checker parts of this later. # Scan the top of the de-litted file for {-# OPTIONS #-} pragmas &check_for_source_options($lit2pgm_hscpp,$ifile); - # options found in the source file take a back seat, i.e., we scan + + # Options found in the source file take a back seat, i.e., we scan # them first. Only process the command line again if source file # contained anything of interest *or* there's more than one # input file (we have to reset the options). @@ -1630,6 +1595,7 @@ Again, we'll do the post-recompilation-checker parts of this later. &setupOptimiseFlags(); &setupMachOpts(); &setupIncPaths(); + &setupWarningFlags(); &setupHeapStackSize(); # @@ -1642,17 +1608,28 @@ Again, we'll do the post-recompilation-checker parts of this later. ? $Do_cc : ( ($HscOut eq '-C=') ? 1 : 0 ); local($do_as) = $Do_as; - local($hsc_out) = ( $HscOut eq '-C=' ) ? "$Tmp_prefix.hc" : "$Tmp_prefix.s" ; + local($hsc_out) = ( $HscOut eq '-C=' ) ? "$Tmp_prefix.hc" : "$Tmp_prefix.s" ; + local($hsc_out_c_stub) = ( $HscOut eq '-C=' ) ? "${Tmp_prefix}_stb.c" : ""; + local($hsc_out_h_stub) = ( $HscOut eq '-C=' ) ? "${Tmp_prefix}_stb.h" : ""; - if ($ifile =~ /.lhs$/ || $ifile =~ /.hs$/ ) { + if ($Only_preprocess_hc) { # stop after having run $Cc -E + $do_as=0; + } + if ($Only_preprocess_C) { # stop after having run $hscpp + $do_hsc=0; $do_cc = 0; $do_as=0; + } elsif ($ifile =~ /.lhs$/ || $ifile =~ /.hs$/ ) { ; } elsif ($ifile =~ /\.hc$/ || $ifile =~ /_hc$/ ) { # || $ifile =~ /\.$Isuffix$/o) # ToDo: better $do_hscpp = 0; $do_hsc = 0; $do_cc = 1; $hsc_out = $ifile; + $hsc_out_c_stub = ''; + $hsc_out_h_stub = ''; } elsif ($ifile =~ /\.c$/) { $do_hscpp = 0; $do_hsc = 0; $do_cc = 1; $hsc_out = $ifile; $is_hc_file = 0; - } elsif ($ifile =~ /\.s$/) { + $hsc_out_c_stub = ''; + $hsc_out_h_stub = ''; + } elsif ($ifile =~ /\.[sS]$/) { $do_hscpp = 0; $do_hsc = 0; $do_cc = 0; $cc_as = $ifile; } else { # don't know what it is, but nothing to do herein... @@ -1662,16 +1639,16 @@ Again, we'll do the post-recompilation-checker parts of this later. # hack to avoid running hscpp $HsCpp = $Cat if ! $Cpp_flag_set; - &runHscpp($in_lit2pgm, $lit2pgm_hscpp, $hscpp_hsc) - if $do_hscpp; + &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."@. + \begin{code} local($going_interactive) = $HscOut eq '-N=' || $ifile_root eq '_stdin'; @@ -1680,7 +1657,7 @@ phase) to @"$ifile_root."@. # -fvia-C (or the equivalent) # if ( $HscOut ne '-C=' && $Keep_hc_file_too ) { - print STDERR "Warning: Native code generator to be used, -keep-hc-file-too will be ignored\n"; + print STDERR "$Pgm: warning: Native code generator to be used, -keep-hc-file-too will be ignored\n"; } if (! $do_cc && ! $do_as) { # stopping after hsc @@ -1694,7 +1671,7 @@ phase) to @"$ifile_root."@. 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'); + : &odir_ify($ifile_root, ( $Only_preprocess_hc ) ? 'i' : 's'); $ofile_target = $cc_as; # reset } @@ -1707,17 +1684,35 @@ Now the Haskell compiler, C compiler, and assembler \begin{code} if ($do_hsc) { &runHscAndProcessInterfaces( $ifile, $hscpp_hsc, $ifile_root, - $ofile_target, $hifile_target); + $ofile_target, $hifile_target, + $going_interactive); + } + + if (-f $hsc_out_h_stub) { + &run_something("cp $hsc_out_h_stub $ofile_h_stub_target", 'Copy foreign export header file'); + } + + if (-f $hsc_out_c_stub) { + &run_something("cp $hsc_out_c_stub $ofile_c_stub_target", 'Copy foreign export C stubs'); + local ($hsc_out_s_stub); + local ($hsc_out_o_stub); + ($ofile_s_stub_target = $ofile_c_stub_target) =~ s/\.(.*)$/\.s/; + ($ofile_o_stub_target = $ofile_c_stub_target) =~ s/\.(.*)$/\.o/; + &runGcc (0, $ofile_c_stub_target, $ofile_s_stub_target); + &runAs ($ofile_o_stub_target, $ofile_s_stub_target); + # + # Bring the C stub protos into scope when compiling the .hc file. + # + push (@CcInjects, "#include \"${hsc_out_h_stub}\"\n"); + # Hack - ensure that the stub .h file is included in the OPTIONS section + # if the .hc file is saved. + push (@File_options, "-#include \"${ofile_h_stub_target}\"\n"); + } if ($do_cc) { -# # if we're going to split up object files, #delete! andre -# # we inject split markers into the .hc file now #delete! andre -# if ( $HscOut eq '-C=' && $SplitObjFiles ) { #delete! andre -# &inject_split_markers ( $hsc_out ); #delete! andre -# } #delete! andre &runGcc ($is_hc_file, $hsc_out, $cc_as_o); - &runMangler($is_hc_file, $cc_as_o, $cc_as, $ifile_root); + &runMangler($is_hc_file, $cc_as_o, $cc_as, $ifile_root) if ! $Only_preprocess_hc; } &split_asm_file($cc_as) if $do_as && $SplitObjFiles; @@ -1734,10 +1729,14 @@ Finally, decide what to queue up for linker input. #ToDo: local($or_isuf) = ($Isuffix eq '') ? '' : "|$Isuffix"; - if ( $ifile !~ /\.(lhs|hs|hc|c|s)$/ && $ifile !~ /_hc$/ ) { - print STDERR "$Pgm: don't recognise suffix on `$ifile'; passing it through to linker\n" - if $ifile !~ /\.a$/; - + if ( $ifile !~ /\.(lhs|hs|hc|c|s|a|S)$/ && $ifile !~ /_hc$/ ) { + # There's sometimes confusion regarding .hi files; users + # supplying them on the command line. + if ( $ifile =~ /\.hi$/ ) { + print STDERR "$Pgm: warning: found `$ifile' on command line; interface files should not be supplied here - ignoring it.\n"; + } else { + print STDERR "$Pgm: don't recognise suffix on `$ifile'; passing it through to linker\n"; + } # oops; we tentatively pushed the wrong thing; fix & do the right thing pop(@Link_file); push(@Link_file, $ifile); } @@ -1756,9 +1755,13 @@ Finally, decide what to queue up for linker input. 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 ); + local($to_do) = ""; + + # Only add #line pragma if we're going to need it. + $to_do = "echo '#line 1 \"$in_lit2pgm\"' > $lit2pgm_hscpp && " if ($Cpp_flag_set); + $to_do .= "$Unlit @Unlit_flags $in_lit2pgm - >> $lit2pgm_hscpp"; + + push(@Files_to_tidy, $lit2pgm_hscpp ); &run_something($to_do, 'literate pre-processor'); } @@ -1768,27 +1771,41 @@ sub runLit2pgm { sub runHscpp { local($in_lit2pgm, $lit2pgm_hscpp, $hscpp_hsc) = @_; - local($to_do); + local($to_do) = ""; + + # Strictly speaking, echoing of the following line pragma is only required + # on non-delit'ed input, as we've already added it during de-lit. However, + # hscpp will then add a {-# LINE 1 "$lit2pgm_hsc" -} to the top of the file, + # which is not very informative (but harmless). Hence, we uniformly have + # {-# LINE 1 "$in_lit2pgm" #-} as the first line to all cpp'ed hsc input. + # + $to_do = "echo '{-# LINE 1 \"$in_lit2pgm\" -}' > $hscpp_hsc && "; if ($HsCpp eq $Cat) { - $to_do = "echo '#line 1 \"$in_lit2pgm\"' > $hscpp_hsc && ". - "$HsCpp $lit2pgm_hscpp >> $hscpp_hsc"; - @Files_to_tidy = ( $hscpp_hsc ); + $to_do .= "$HsCpp $lit2pgm_hscpp >> $hscpp_hsc"; + push(@Files_to_tidy, $hscpp_hsc ); &run_something($to_do, 'Ineffective C pre-processor'); } else { local($includes) = '-I' . join(' -I',@Include_dir); - $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 ); + $to_do .= "$HsCpp $Verbose @HsCpp_flags @HsSourceCppOpts $includes $lit2pgm_hscpp >> $hscpp_hsc"; + push(@Files_to_tidy, $hscpp_hsc ); &run_something($to_do, 'Haskellised C pre-processor'); } + + if ( $Only_preprocess_C ) { + $to_do = "$Cat $hscpp_hsc"; + &run_something($to_do, ''); + } + } \end{code} \begin{code} sub runHscAndProcessInterfaces { - local($ifile, $hscpp_hsc, $ifile_root, $ofile_target, $hifile_target) = @_; + local($ifile, $hscpp_hsc, $ifile_root, + $ofile_target, $hifile_target, + $going_interactive) = @_; # $ifile is the original input file # $hscpp_hsc post-unlit, post-cpp, etc., input file @@ -1806,7 +1823,7 @@ sub runHscAndProcessInterfaces { $i_atime,$i_mtime,$i_ctime,$i_blksize,$i_blocks) = stat($ifile); # The informational messages below are now conditional on -v being set -- SOF - if ( ! -f $ofile_target ) { + if ( $ofile_target ne "_stdin.s" && ! -f $ofile_target ) { print STDERR "$Pgm:compile:Output file $ofile_target doesn't exist\n" if $Verbose; $source_unchanged = 0; } @@ -1814,7 +1831,7 @@ sub runHscAndProcessInterfaces { ($o_dev,$o_ino,$o_mode,$o_nlink,$o_uid,$o_gid,$o_rdev,$o_size, $o_atime,$o_mtime,$o_ctime,$o_blksize,$o_blocks) = stat(_); # stat info from -f test - if ( ! -f $hifile_target ) { + if ( $hifile_target ne "_stdout" && ! -f $hifile_target ) { print STDERR "$Pgm:compile:Interface file $hifile_target doesn't exist\n" if $Verbose; $source_unchanged = 0; } @@ -1822,11 +1839,14 @@ sub runHscAndProcessInterfaces { ($hi_dev,$hi_ino,$hi_mode,$hi_nlink,$hi_uid,$hi_gid,$hi_rdev,$hi_size, $hi_atime,$hi_mtime,$hi_ctime,$hi_blksize,$hi_blocks) = stat(_); # stat info from -f test - if ($i_mtime > $o_mtime) { + if ( $ofile_target ne "_stdin.s" && $i_mtime > $o_mtime) { print STDERR "$Pgm:recompile:Input file $ifile newer than $ofile_target\n" if $Verbose; $source_unchanged = 0; } + # Tell the compiler which version we're using + push(@HsC_flags, "-fhi-version=${ProjectVersionInt}"); + # So if source_unchanged is still "1", we pass on the good news to the compiler # The -recomp flag can disable this, forcing recompilation if ($Do_recomp_chkr && $source_unchanged) { @@ -1835,7 +1855,7 @@ sub runHscAndProcessInterfaces { # Run the compiler - &runHsc($ifile_root, $hsc_out, $hsc_hi, $going_interactive); + &runHsc($ifile_root, $hsc_out, $hsc_hi, $hsc_out_c_stub, $hsc_out_h_stub, $going_interactive); # See if it bailed out early, saying nothing needed doing. # We work this out by seeing if it created an output .hi file @@ -1908,29 +1928,28 @@ sub runHscAndProcessInterfaces { \begin{code} sub runHsc { - local($ifile_root, $hsc_out, $hsc_hi, $going_interactive) = @_; + local($ifile_root, $hsc_out, $hsc_hi, $hsc_out_c_stub, $hsc_out_h_stub, $going_interactive) = @_; # prepend comma to HsP flags (so hsc can tell them apart...) foreach $a ( @HsP_flags ) { $a = ",$a" unless $a =~ /^,/; } &makeHiMap() unless $HiMapDone; - #print STDERR "HiIncludes: $HiIncludeString\n"; push(@HsC_flags, "-himap=$HiIncludeString"); # here, we may produce .hc/.s and/or .hi files local($output) = ''; - @Files_to_tidy = (); + #@Files_to_tidy = (); if ( $going_interactive ) { - # don't need .hi unless going to show it on stdout: + # don't need .hi unless we're 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... } # 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 ); + $output = "$ProduceHi$hsc_hi $HscOut$hsc_out -F=$hsc_out_c_stub -FH=$hsc_out_h_stub"; + push(@Files_to_tidy, $hsc_hi, $hsc_out, $hsc_out_c_stub, $hsc_out_h_stub ); # if we're compiling foo.hs, we want the GC stats to end up in foo.stat if ( $CollectingGCstats ) { @@ -1941,6 +1960,7 @@ sub runHsc { if ( $CollectGhcTimings ) { # assume $RTS_style eq 'ghc' # emit nofibbish time/bytes-alloc stats to stderr; # see later .stat file post-processing + print STDERR "warning: both -Rgc-stats and -Rghc-timing used, -Rghc-timing wins." if $CollectingGCstats; push(@HsC_rts_flags, "-s$Tmp_prefix.stat"); push(@Files_to_tidy, "$Tmp_prefix.stat"); } @@ -1952,7 +1972,28 @@ sub runHsc { } local($to_do); - $to_do = "$HsC @HsP_flags ,$hscpp_hsc $dump @HsC_flags $CoreLint $StgLint $Verbose $output +RTS @HsC_rts_flags"; + # Win32 only: If the command processor used by system() + # exec()s the application as an ordinary Win32 executable, + # we're in trouble here, since the command line is likely + # to be > 255 chars long. To work around this situation, + # $HsC also understands `at-files', i.e., `@file' on the + # command line will cause $HsC to add the contents of `file' + # to the command line. + # + # [ Note: support for `at-files' is not compiled in by default ] + $cmd_line_opts_via_at_file=0; + if ($cmd_line_opts_via_at_file) { + + local($to_do_opts) = "$Tmp_prefix.opts"; + open(OPTS, "> $Tmp_prefix.opts") || &tidy_up_and_die(1,"Can't open $Tmp_prefix.opts\n"); + print OPTS "$dump @HsC_flags $CoreLint $StgLint $Verbose"; + close(OPTS); + $to_do = "$HsC @HsP_flags ,$hscpp_hsc \@$Tmp_prefix.opts $output +RTS @HsC_rts_flags"; + + } else { + + $to_do = "$HsC @HsP_flags ,$hscpp_hsc $dump @HsC_flags $CoreLint $StgLint $Verbose $output +RTS @HsC_rts_flags"; + } &run_something($to_do, 'Haskell compiler'); # finish business w/ nofibbish time/bytes-alloc stats @@ -2039,13 +2080,15 @@ sub runGcc { local($c_flags) = "@CcBoth_flags"; local($ddebug_flag) = ( $DEBUGging ) ? '-DDEBUG' : ''; + $c_flags .= "-mno-cygwin" if ( $TargetPlatform =~ /-mingw32$/ ); + # "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 =~ /^(powerpc|rs6000|hppa|i386)/) ? $cc_as_o : $cc_as; + $s_output = (($is_hc_file && $DoAsmMangling) || $TargetPlatform =~ /^(powerpc|rs6000|hppa)/) ? $cc_as_o : $cc_as; $c_flags .= " @CcRegd_flags"; $c_flags .= ($is_hc_file) ? " @CcRegd_flags_hc" : " @CcRegd_flags_c"; @@ -2054,32 +2097,35 @@ sub runGcc { open(TMP, "> $cc_help") || &tidy_up_and_die(1,"$Pgm: failed to open `$cc_help' (to write)\n"); if ( $is_hc_file ) { print TMP <= 0; + } else { + # Straight .c files may want to know that they're being used + # with a particular version of GHC, so we define __GLASGOW_HASKELL__ for their benefit. + print TMP "#define __GLASGOW_HASKELL__ ${ProjectVersionInt}\n"; } # 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! + # Don't redirect stderr into intermediate file if slamming output onto stdout (e.g., with -E) + local($fuse_stderr) = "2>&1" if ! $Only_preprocess_hc; + local($to_do) = "$cc $Verbose $ddebug_flag $c_flags @Cpp_define $includes $cc_help > $Tmp_prefix.ccout $fuse_stderr && ( if [ $cc_help_s != $s_output ] ; then mv $cc_help_s $s_output ; else exit 0 ; fi )"; + + if ( $Only_preprocess_hc ) { # HACK ALERT! $to_do =~ s/ -S\b//g; } - @Files_to_tidy = ( $cc_help, $cc_help_s, $s_output ); - $PostprocessCcOutput = 1; # hack, dear hack... + push(@Files_to_tidy, $cc_help, $cc_help_s, $s_output ); + $PostprocessCcOutput = 1 if ! $Only_preprocess_hc; # hack, dear hack... &run_something($to_do, 'C compiler'); $PostprocessCcOutput = 0; + if ( $Only_preprocess_hc ) { + system("$Cat $Tmp_prefix.ccout"); + } unlink($cc_help, $cc_help_s); } \end{code} @@ -2088,38 +2134,15 @@ EOINCL 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) { + if ($is_hc_file && $DoAsmMangling) { + # 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"); # post-process the assembler [.hc files only] &mangle_asm($cc_as_o, $cc_as); - -#OLD: for sanity: -#OLD: local($target) = 'oops'; -#OLD: $target = '-alpha' if $TargetPlatform =~ /^alpha-/; -#OLD: $target = '-hppa' if $TargetPlatform =~ /^hppa/; -#OLD: $target = '-old-asm' if $TargetPlatform =~ /^i386-/; -#OLD: $target = '-m68k' if $TargetPlatform =~ /^m68k-/; -#OLD: $target = '-mips' if $TargetPlatform =~ /^mips-/; -#OLD: $target = '' if $TargetPlatform =~ /^powerpc-/; -#OLD: $target = '-solaris' if $TargetPlatform =~ /^sparc-sun-solaris2/; -#OLD: $target = '-sparc' if $TargetPlatform =~ /^sparc-sun-sunos4/; -#OLD: -#OLD: if ( $target ne '' ) { -#OLD: require("ghc-asm$target.prl") -#OLD: || &tidy_up_and_die(1,"$Pgm: panic: can't load ghc-asm$target.prl!\n"); -#OLD: &mangle_asm($cc_as_o, "$cc_as-2"); # the OLD one! -#OLD: &run_something("$Cmp -s $cc_as-2 $cc_as || $Diff $cc_as-2 $cc_as 1>&2 || exit 0", -#OLD: "Diff'ing old and new mangled .s files"); # NB: to stderr -#OLD: } - } elsif ($TargetPlatform =~ /^hppa/) { # minor mangling of non-threaded files for hp-pa only require('ghc-asm.prl') @@ -2131,11 +2154,6 @@ sub runMangler { require('ghc-asm.prl') || &tidy_up_and_die(1,"$Pgm: panic: can't load ghc-asm-powerpc.prl!\n"); &mini_mangle_asm_powerpc($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... @@ -2151,9 +2169,12 @@ sub runAs { local($asmblr) = ( $As ) ? $As : $CcRegd; + # need to add the -I flags in case the file is going through cpp (.S files) + local($includes) = '-I' . join(' -I', @Include_dir); + if ( ! $SplitObjFiles ) { - local($to_do) = "$asmblr -o $as_out -c @As_flags $cc_as"; - @Files_to_tidy = ( $as_out ); + local($to_do) = "$asmblr -o $as_out -c @As_flags $includes $cc_as"; + push(@Files_to_tidy, $as_out ); &run_something($to_do, 'Unix assembler'); } else { # more complicated split-ification... @@ -2173,7 +2194,7 @@ sub runAs { 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 ); + push(@Files_to_tidy, $split_out ); &run_something($to_do, 'Unix assembler'); } @@ -2231,16 +2252,10 @@ sub run_something { open(CCOUT, "< $Tmp_prefix.ccout") || &tidy_up_and_die(1,"$Pgm: failed to open `$Tmp_prefix.ccout'\n"); while ( ) { - next if /attribute directive ignored/; next if /call-clobbered/; - next if /from .*COptRegs\.lh/; - next if /from .*(stg|rts)defs\.h:/; + next if /control reaches end/; + next if /from .*Stg\.h:/; next if /from ghc\d+.c:\d+:/; - next if /from .*\.lc/; - next if /from .*SMinternal\.l?h/; - next if /ANSI C does not support \`long long\'/; - next if /warning:.*was declared \`extern\' and later \`static\'/; - next if /warning: assignment discards \`const\' from pointer target type/; next if /: At top level:$/; next if /: In function \`.*\':$/; next if /\`ghc_cc_ID\' defined but not used/; @@ -2253,7 +2268,6 @@ sub run_something { if ($Using_dump_file) { print STDERR "Compilation Errors dumped in $Specific_dump_file\n"; } - &tidy_up_and_die($return_val, ''); } $Using_dump_file = 0; @@ -2274,20 +2288,31 @@ sub process_ghc_timings { local($SysSpecificTiming) = 'ghc'; open(STATS, $StatsFile) || die "Failed when opening $StatsFile\n"; - local($tot_live) = 0; # for calculating avg residency + local($max_live) = 0; + local($tot_live) = 0; # for calculating residency stuff + local($tot_samples) = 0; while () { - $tot_live += $1 if /^\s*\d+\s+\d+\s+\d+\.\d+\%\s+(\d+)\s+\d+\.\d+\%/; - - $BytesAlloc = $1 if /^\s*([0-9,]+) bytes allocated in the heap/; + if (! /Gen:\s+0/ && ! /Minor/ && /^\s*\d+\s+\d+\s+(\d+)\s+\d+\.\d+/ ) { + $max_live = $1 if $max_live < $1; + $tot_live += $1; + $tot_samples += 1; + } + $BytesAlloc = $1 if /^\s*([0-9,]+) bytes allocated in the heap/; if ( /^\s*([0-9,]+) bytes maximum residency .* (\d+) sample/ ) { $MaxResidency = $1; $ResidencySamples = $2; } - $GCs = $1 if /^\s*([0-9,]+) garbage collections? performed/; + $GCs = $1 if /^\s*([0-9,]+) (collections? in generation 0|garbage collections? performed)/; - if ( /^\s*INIT\s+time\s*(\d+\.\d\d)s\s*\(\s*(\d+\.\d\d)s elapsed\)/ ) { + if ( /^\s+([0-9]+)\s+Mb total memory/ ) { + $TotMem = $1; + } + + # The presence of -? in the following pattern is only there to + # accommodate 0.29 && <= 2.05 RTS' + if ( /^\s*INIT\s+time\s*(\d+\.\d\d)s\s*\(\s*-?(\d+\.\d\d)s elapsed\)/ ) { $InitTime = $1; $InitElapsed = $2; } elsif ( /^\s*MUT\s+time\s*(\d+\.\d\d)s\s*\(\s*(\d+\.\d\d)s elapsed\)/ ) { $MutTime = $1; $MutElapsed = $2; @@ -2296,8 +2321,10 @@ sub process_ghc_timings { } } close(STATS) || die "Failed when closing $StatsFile\n"; - if ( defined($ResidencySamples) && $ResidencySamples > 0 ) { - $AvgResidency = int ($tot_live / $ResidencySamples) ; + if ( $tot_samples > 0 ) { + $ResidencySamples = $tot_samples; + $MaxResidency = $max_live; + $AvgResidency = int ($tot_live / $tot_samples) ; } # warn about what we didn't find @@ -2328,7 +2355,7 @@ sub process_ghc_timings { # print out what we found print STDERR "<<$SysSpecificTiming: ", - "$BytesAlloc bytes, $GCs GCs, $AvgResidency/$MaxResidency avg/max bytes residency ($ResidencySamples samples), $InitTime INIT ($InitElapsed elapsed), $MutTime MUT ($MutElapsed elapsed), $GcTime GC ($GcElapsed elapsed)", + "$BytesAlloc bytes, $GCs GCs, $AvgResidency/$MaxResidency avg/max bytes residency ($ResidencySamples samples), ${TotMem}M in use, $InitTime INIT ($InitElapsed elapsed), $MutTime MUT ($MutElapsed elapsed), $GcTime GC ($GcElapsed elapsed)", " :$SysSpecificTiming>>\n"; # OK, party over @@ -2382,7 +2409,7 @@ nonsensical). sub grab_arg_arg { local(*Args, $option, $rest_of_arg) = @_; - if ($rest_of_arg) { + if ($rest_of_arg ne '') { return($rest_of_arg); } elsif ($#Args >= 0) { local($temp) = $Args[0]; shift(@Args); @@ -2429,6 +2456,197 @@ sub add_Hsc_flags { } \end{code} +To add another system library, you'll need to augment the +Supported_syslibs variable with name and info on your addition +to the syslib family. The info bit consist of the following: + + - interface file directory + see the misc or posix entry for how to distinguish + between using installed and build tree directories. + + - directory location of archives + + - location of (way-independent) C support libs. + not all libraries need this - if you don't, just + give the empty string. + - list of syslibs you depend on. + + - additional ghc command line flags that should be used. + - additional C compiler command line flags that should be used. + - link + + +\begin{code} + +# Hash to keep track of +%Syslibs_added = (); + +sub add_syslib { + local($syslib) = @_; + + # Lifting this out of this sub brings it out of scope - why?? + %Supported_syslibs = + ( exts, + [ # where to slurp interface files from + ( $INSTALLING + ? "$InstLibDirGhc/imports/exts" + : "$TopPwd/$CURRENT_DIR/$GHC_LIB_DIR/exts" + ) + , # where to find the archive to use when linking + ( $INSTALLING + ? "$InstLibDirGhc" + : "$TopPwd/$CURRENT_DIR/$GHC_LIB_DIR/exts" + ) + , '' # no cbits + , '' # Syslib dependencies + , '' # extra ghc opts + , '' # extra cc opts + , '' # extra ld opts + ], + + misc, + [ # where to slurp interface files from + ( $INSTALLING + ? "$InstLibDirGhc/imports/misc" + : "$TopPwd/$CURRENT_DIR/$GHC_LIB_DIR/misc" + ) + , # where to find the archive to use when linking + ( $INSTALLING + ? "$InstLibDirGhc" + : "$TopPwd/$CURRENT_DIR/$GHC_LIB_DIR/misc" + ) + , # where to find the cbits archive to use when linking + ( $INSTALLING + ? "$InstLibDirGhc" + : "$TopPwd/$CURRENT_DIR/$GHC_LIB_DIR/misc/cbits" + ) + , 'exts' # Syslib dependencies + , '' # extra ghc opts + , '' # extra cc opts + , ( $TargetPlatform =~ /-solaris2$/ ? '-lnsl -lsocket' : '') + ], + hbc, + [ # where to slurp interface files from + ( $INSTALLING + ? "$InstLibDirGhc/imports/hbc" + : "$TopPwd/CONTRIB/libraries/hbc/src" + ) + , # where to find the archive to use when linking + ( $INSTALLING + ? "$InstLibDirGhc" + : "$TopPwd/CONTRIB/libraries/src/hbc" + ) + , # where to find the cbits archive to use when linking + ( $INSTALLING + ? "$InstLibDirGhc" + : "$TopPwd/CONTRIB/libraries/hbc/cbits" + ) + , 'exts' # Syslib dependencies + , '' # extra ghc opts + , '' # extra cc opts + , '' + ], + posix, + [ # where to slurp interface files from + ( $INSTALLING + ? "$InstLibDirGhc/imports/posix" + : "$TopPwd/$CURRENT_DIR/$GHC_LIB_DIR/posix" + ) + , # where to find the archive to use when linking + ( $INSTALLING + ? "$InstLibDirGhc" + : "$TopPwd/$CURRENT_DIR/$GHC_LIB_DIR/posix" + ) + , # where to find the cbits archive to use when linking + ( $INSTALLING + ? "$InstLibDirGhc" + : "$TopPwd/$CURRENT_DIR/$GHC_LIB_DIR/posix/cbits" + ) + , 'misc' # Syslib dependencies + , '' # extra ghc opts + , '' # extra cc opts + , '' # extra ld opts + ], + concurrent, + [ # where to slurp interface files from + ( $INSTALLING + ? "$InstLibDirGhc/imports/concurrent" + : "$TopPwd/$CURRENT_DIR/$GHC_LIB_DIR/concurrent" + ) + , # where to find the archive to use when linking + ( $INSTALLING + ? "$InstLibDirGhc" + : "$TopPwd/$CURRENT_DIR/$GHC_LIB_DIR/concurrent" + ) + , '' # where to find the cbits archive to use when linking + , '' # Syslib dependencies + , '' # extra ghc opts + , '' # extra cc opts + , '' # extra ld opts + ], + win32, + [ # where to slurp interface files from + ( $INSTALLING + ? "$InstLibDirGhc/imports/win32" + : "$TopPwd/hslibs/win32/src" + ) + , # where to find the archive to use when linking + ( $INSTALLING + ? "$InstLibDirGhc" + : "$TopPwd/hslibs/win32/src" + ) + , '' + , 'exts' # Syslib dependencies + , '' # extra ghc opts + , '' # extra cc opts + , '-luser32 -lgdi32' # extra ld opts + ] + ); + + # check if it's supported.. + + if ( !exists $Supported_syslibs{$syslib} ) { + print STDERR "$Pgm: no such system library (-syslib): $syslib\n"; + $Status++; + return; + } + + # This check is here to avoid syslib loops from + # spoiling the party. A side-effect of it is that + # it disallows multiple mentions of a syslib on a command-line, + # explicit *and* implicit ones (i.e., "-syslib exts -syslib misc" + # is not equal to "-syslib exts -syslib misc -syslib exts", + # which it needs to be) + # + # Since our current collection of syslibs don't have any + # loops, this test is disabled. + # + # ToDo: loop avoidance scheme when the need arises + # + #return if ( exists $Syslibs_added{$syslib} ); + + $Syslibs_added{$syslib} = 1; + + local ($hi_dir, $lib_dir, $lib_cbits_dir, + $syslib_deps, $syslib_ghc_opts, + $syslib_cc_opts, $syslib_ld_opts) = @{ $Supported_syslibs{$syslib} }; + + + unshift(@SysImport_dir, $hi_dir); + push(@SysLibrary_dir, $lib_dir); + push(@SysLibrary_dir, $lib_cbits_dir) if ( $lib_cbits_dir ne ''); + + push(@SysLibrary, "-lHS$syslib"); + push(@SysLibrary, "-lHS${syslib}_cbits") if ( $lib_cbits_dir ne ''); + push(@SysLibrary, $syslib_ld_opts) if ($syslib_ld_opts ne ''); + + # Add on any extra dependencies. + foreach $lib (split(' ',$syslib_deps)) { + &add_syslib($lib); + } +} +\end{code} + Source files may have {-# OPTIONS ... #-} pragmas at the top, containing command line options we want to append to collection of commands specified directly. @check_for_source_options@ looks at the top of a de-lit'ified Haskell @@ -2462,7 +2680,10 @@ sub check_for_source_options { elsif ( /^$/ ) { # ignore empty lines ; } - elsif ( /^#line.+$/ ) { # ignore comment lines + elsif ( /^#line.+$/ ) { # ignore comment lines (unused..ToDo: rm ) + ; + } + elsif ( /^{-# LINE.+$/ ) { # ignore line pragmas ; } else { # stop looking, something non-empty / not @@ -2492,11 +2713,11 @@ sub splitCmdLine { arg: while($_ = $args[0]) { shift(@args); # sigh, we have to deal with these -option arg specially here. - /^-(tmpdir|odir|o|isuf|osuf|hisuf|hisuf-prelude|odump|syslib)$/ && + /^-(tmpdir|odir|ohi|o|isuf|osuf|hisuf|odump|syslib)$/ && do { push(@Cmd_opts, $_); push(@Cmd_opts,$args[0]); shift(@args); next arg; }; - /^-./ && do { push(@Cmd_opts, $_); next arg; }; + /^--?./ && do { push(@Cmd_opts, $_); next arg; }; - if (/\.[oa]$/) { + if (/\.([^_]+_)?[oa]$/) { push(@Link_file, $_); } else { push(@Input_file, $_); @@ -2556,13 +2777,13 @@ arg: while($_ = $Args[0]) { if (/^-\?$/ || /^--?help$/) { print $LongUsage; exit $Status; } #-----------version ---------------------------------------------------- - /^--version$/ && do { print STDERR "${PROJECTNAME}, version ${PROJECTVERSION}, patchlevel ${PROJECTPATCHLEVEL}\n"; exit $Status; }; + /^--version$/ && do { print STDERR "${ProjectName}, version ${ProjectVersion}, patchlevel ${ProjectPatchLevel}\n"; exit $Status; }; #---------- verbosity and such ----------------------------------------- /^-v$/ && do { $Verbose = '-v'; $Time = 'time'; next arg; }; #---------- what phases are to be run ---------------------------------- - /^-recomp/ && do { $Do_recomp_chkr = 1; next arg; }; + /^-(no-)?recomp/ && do { $Do_recomp_chkr = ($1 eq '') ? 1 : 0; next arg; }; /^-cpp$/ && do { $Cpp_flag_set = 1; next arg; }; # change the global default: @@ -2577,15 +2798,20 @@ arg: while($_ = $Args[0]) { next arg; }; # leave out actual C generation (debugging) [also turns off interface gen] - /^-hi$/ && do { $HiOnStdout = 1; $ProduceHi = '-hifile='; next arg; }; + + /^-hi$/ && do { $HiOnStdout = 1; $ProduceHi = '-hifile='; next arg; }; # _do_ generate an interface; usually used as: -noC -hi + /^-hi-with-(.*)$/ && do { $HiOnStdout = 1; $HiWith .= " $1" ; $ProduceHi = '-hifile='; next arg; }; + # limit ourselves to outputting a particular section. /^-nohi$/ && do { $ProduceHi = '-nohifile='; next arg; }; # don't generate an interface (even if generating C) - /^-hi-diffs$/ && do { $HiDiff_flag = 'normal'; next arg; }; - /^-hi-diffs-with-usages$/ && do { $HiDiff_flag = 'usages'; next arg; }; - /^-no-hi-diffs$/ && do { $HiDiff_flag = ''; next arg; }; + /^-hi-diffs$/ && do { $HiDiff_flag = 'normal'; next arg; }; + /^-hi-diffs-with-usages$/ && do { $HiDiff_flag = 'usages'; next arg; }; + /^-no-hi-diffs$/ && do { $HiDiff_flag = ''; next arg; }; + /^-keep-hi-diffs$/ && do { $Keep_HiDiffs = 1; next arg; }; + # show/disable diffs if the interface file changes /^-E$/ && do { push(@CcBoth_flags, '-E'); @@ -2672,13 +2898,6 @@ arg: while($_ = $Args[0]) { $Status++; } next arg; }; - # ToDo: remove, not a `normal' user thing to do (should be automatic) - /^-hisuf-prelude$/ && do { $HiSuffix_prelude = &grab_arg_arg(*Args,'-hisuf-prelude', ''); - if ($HiSuffix =~ /\./ ) { - print STDERR "$Pgm: -hisuf-prelude suffix shouldn't contain a .\n"; - $Status++; - } - next arg; }; /^-odump$/ && do { $Specific_dump_file = &grab_arg_arg(*Args,'-odump', ''); if ($Specific_dump_file =~ /(.*)\/[^\/]*$/) { local($dir_part) = $1; @@ -2722,13 +2941,12 @@ arg: while($_ = $Args[0]) { : '-fauto-sccs-on-exported-toplevs'; next arg; }; - #--------- ticky/concurrent/parallel ----------------------------------- + #--------- ticky/parallel ---------------------------------------------- # we sort out the details a bit later on - /^-concurrent$/ && do { $CONCURing = 'c'; next arg; }; # concurrent Haskell - /^-gransim$/ && do { $GRANing = 'g'; next arg; }; # GranSim + /^-gransim$/ && do { $GRANing = 'g'; &add_syslib('concurrent'); next arg; }; # GranSim /^-ticky$/ && do { $TICKYing = 't'; next arg; }; # ticky-ticky - /^-parallel$/ && do { $PARing = 'p'; next arg; }; # parallel Haskell + /^-parallel$/ && do { $PARing = 'p'; &add_syslib('concurrent'); next arg; }; # parallel Haskell #-------------- "user ways" -------------------------------------------- @@ -2764,27 +2982,7 @@ arg: while($_ = $Args[0]) { /^-l(.*)/ && do { push(@UserLibrary,'-l'.&grab_arg_arg(*Args,'-l', $1)); next arg; }; /^-syslib(.*)/ && do { local($syslib) = &grab_arg_arg(*Args,'-syslib',$1); - print STDERR "$Pgm: no such system library (-syslib): $syslib\n", - $Status++ unless $syslib =~ /^(hbc|ghc|posix|contrib)$/; - - unshift(@SysImport_dir, - ${INSTALLING} - ? "$InstSysLibDir/$syslib/imports" - : "$TopPwd/hslibs/$syslib/src"); - - if ( ${INSTALLING} ) { - push(@SysLibrary_dir, - ("$InstSysLibDir")); - } else { - push(@SysLibrary_dir, - ("$TopPwd/hslibs/$syslib" - ,"$TopPwd/hslibs/$syslib/cbits")); - } - - push(@SysLibrary, "-lHS$syslib"); - push(@SysLibrary, "-lHS${syslib}_cbits") - unless $syslib eq 'contrib'; #HACK! it has no cbits - + &add_syslib($syslib); next arg; }; #======================================================================= @@ -2808,7 +3006,8 @@ arg: while($_ = $Args[0]) { /^-optP(.*)$/ && do { push(@HsCpp_flags, $1); next arg; }; /^-optCrts(.*)$/&& do { push(@HsC_rts_flags, $1); next arg; }; /^-optC(.*)$/ && do { push(@HsC_flags, $1); next arg; }; - /^-optcpp(.*)$/ && do { push(@Cpp_define, $1); next arg; }; + /^-optp(.*)$/ && do { push(@HsP_flags, $1); next arg; }; + /^-optcpp(.*)$/ && do { push(@Cpp_define, $1); $Only_preprocess_hc = ($1 eq "-E"); 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; }; @@ -2818,10 +3017,6 @@ arg: while($_ = $Args[0]) { /^-D(.*)/ && do { push(@HsCpp_flags, "'-D".&grab_arg_arg(*Args,'-D',$1)."'"); next arg; }; /^-U(.*)/ && do { push(@HsCpp_flags, "'-U".&grab_arg_arg(*Args,'-U',$1)."'"); next arg; }; - /^-genSPECS/ && do { $Cpp_flag_set = 1; - $genSPECS_flag = $_; - next arg; }; - #---------- post-Haskell "assembler"------------------------------------ /^-ddump-raw-asm$/ && do { $Dump_raw_asm = 1; next arg; }; /^-ddump-asm-splitting-info$/ && do { $Dump_asm_splitting_info = 1; next arg; }; @@ -2831,31 +3026,23 @@ arg: while($_ = $Args[0]) { /^-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 { next arg; }; # a no-op right now - /^-fignore-interface-pragmas$/ && do { push(@HsC_flags, $_); next arg; }; /^-fno-implicit-prelude$/ && do { $NoImplicitPrelude= 1; push(@HsC_flags, $_); next arg; }; - # don't do stack checking using page fault `trick'. - # (esoteric). - /^-fstack-check$/ && do { $StkChkByPageFaultOK = 0; next arg; }; + # # have the compiler proper generate concurrent code, # really only used when you want to configure your own - # special user compilation way. (Use -concurrent when - # compiling `Concurrent Haskell' programs). + # special user compilation way. # - # (ditto for -fgransim, fscc-profiling and -fticky-ticky) + # (ditto for -fgransim, fscc-profiling, -fparallel and -fticky-ticky) # - /^-fconcurrent$/ && do { push(@HsC_flags,$_); next arg; }; /^-fscc-profiling$/ && do { push(@HsC_flags,$_); next arg; }; /^-fticky-ticky$/ && do { push(@HsC_flags,$_); next arg; }; /^-fgransim$/ && do { push(@HsC_flags,$_); next arg; }; + /^-fparallel$/ && do { push(@HsC_flags,$_); next arg; }; - /^-user-prelude-force/ && do { # ignore if not -user-prelude - next arg; }; - - /^-split-objs/ && do { + /^-split-objs$/ && do { if ( $TargetPlatform !~ /^(alpha|hppa1\.1|i386|m68k|mips|powerpc|rs6000|sparc)-/ ) { $SplitObjFiles = 0; print STDERR "WARNING: don't know how to split objects on this platform: $TargetPlatform\n`-split-objs' option ignored\n"; @@ -2871,18 +3058,19 @@ arg: while($_ = $Args[0]) { } next arg; }; + /^-fno-asm-mangling$/ && do { $DoAsmMangling = 0; next arg; }; + + /^-fallow-overlapping-instances$/ && do { push(@HsC_flags, $_); next arg; }; + /^-fallow-undecidable-instances$/ && do { push(@HsC_flags, $_); next arg; }; /^-fglasgow-exts$/ && do { push(@HsC_flags, $_); push(@HsP_flags, '-N'); -# push(@HsC_flags, '-fshow-import-specs'); + # -fglasgow-exts implies -syslib exts + &add_syslib('exts'); next arg; }; - /^-fspeciali[sz]e-unboxed$/ - && do { $Oopt_DoSpecialise = '-fspecialise'; - $Oopt_SpecialiseUnboxed = '-fspecialise-unboxed'; - next arg; }; /^-fspeciali[sz]e$/ && do { $Oopt_DoSpecialise = '-fspecialise'; next arg; }; /^-fno-speciali[sz]e$/ @@ -2923,13 +3111,15 @@ arg: while($_ = $Args[0]) { # --------------- /^-fasm-(.*)$/ && do { $HscOut = '-S='; next arg; }; # force using nativeGen - /^-fvia-C$/ && do { $HscOut = '-C='; next arg; }; # force using C compiler + /^-fvia-[cC]$/ && do { $HscOut = '-C='; next arg; }; # force using C compiler # --------------- - /^(-funfolding-use-threshold)(.*)$/ - && do { $Oopt_UnfoldingUseThreshold = $1 . &grab_arg_arg(*Args,$1, $2); - next arg; }; + /^-funfolding-.*$/ + && do { push(@HsC_flags, $_); next arg }; + + /^-funfold-casms-in-hi-file$/ + && do { push(@HsC_flags, $_); next arg }; /^(-fmax-simplifier-iterations)(.*)$/ && do { $Oopt_MaxSimplifierIterations = $1 . &grab_arg_arg(*Args,$1, $2); @@ -2938,35 +3128,35 @@ arg: while($_ = $Args[0]) { /^-fno-pedantic-bottoms$/ && do { $Oopt_PedanticBottoms = ''; next arg; }; + /^-fno-pre-inlining$/ + && do { push(@HsC_flags, $_); next arg }; + /^-fdo-monad-eta-expansion$/ && do { $Oopt_MonadEtaExpansion = $_; next arg; }; /^-fno-let-from-(case|app|strict-let)$/ # experimental, really (WDP 95/10) && do { push(@HsC_flags, $_); next arg; }; - /^(-freturn-in-regs-threshold)(.*)$/ - && do { local($what) = $1; - local($num) = &grab_arg_arg(*Args,$what, $2); - if ($num < 2 || $num > 8) { - die "Bad experimental flag: $_\n"; - } else { - $HscOut = '-C='; # force using C compiler - push(@HsC_flags, "$what$num"); - push(@CcRegd_flags, "-D__STG_REGS_AVAIL__=$num"); - } - next arg; }; - # --------------- Warnings etc. ------ - /^-f(show-import-specs)/ - && do { push(@HsC_flags, $_); next arg; }; + /^-fwarn-(.*)$/ && do { push(@HsC_flags, $_); next arg; }; - # for now, just -fwarn-name-shadowing - /^-fwarn-(.*)$/ && do { push(@HsC_flags, $_); next arg; }; /^-fno-(.*)$/ && do { push(@HsC_antiflags, "-f$1"); &squashHscFlag("-f$1"); next arg; }; + /^-W$/ && do { push(@HsC_flags, @MinusWOpts); next arg; }; + /^-Wall$/ && do { push(@HsC_flags, @MinusWallOpts); next arg; }; + /^(-Wnot|w)$/ && do { foreach (@Hsc_flags) { + /^-fwarn-(.*)$/ && do { $_=''; }; + }; + push(@HsC_antiflags, @StandardWarnings); + next arg; }; + + # --------------- fun stuff ---------------- + + /^-freport-compile$/ && do { push(@HsC_flags, $_); next arg; }; + # --------------- platform specific flags (for gcc mostly) ---------------- /^-mlong-calls$/ && do { # for GCC for HP-PA boxes, @@ -2996,6 +3186,7 @@ arg: while($_ = $Args[0]) { /^-d(dump|ppr)-/ && do { push(@HsC_flags, $_); next arg; }; /^-dverbose-(simpl|stg)/ && do { push(@HsC_flags, $_); next arg; }; /^-dshow-passes/ && do { push(@HsC_flags, $_); next arg; }; + /^-dshow-rn-stats/ && do { push(@HsC_flags, $_); next arg; }; /^-dshow-rn-trace/ && do { push(@HsC_flags, $_); next arg; }; /^-dsource-stats/ && do { push(@HsC_flags, $_); next arg; }; /^-dsimplifier-stats/ && do { push(@HsC_flags, $_); next arg; }; @@ -3028,7 +3219,7 @@ arg: while($_ = $Args[0]) { } next arg; }; - /^-(K|Rmax-(stk|stack)size)(.*)/ && do { + /^(-K|Rmax-(stk|stack)size)(.*)/ && do { local($flag) = $1; local($stk_size) = &grab_arg_arg(*Args,'-Rmax-stksize', $3); if ($stk_size =~ /(\d+)[Kk]$/) { @@ -3074,7 +3265,8 @@ arg: while($_ = $Args[0]) { #---------- Linker (gcc, really) --------------------------------------- - /^-static$/ && do { push(@Ld_flags, $_); next arg; }; + /^-static$/ && do { push(@HsC_flags, $_); push(@Ld_flags, $_); next arg; }; + /^-no-hs-main$/ && do { $NoHaskellMain=1; next arg; }; #---------- mixed cc and linker magic ---------------------------------- # this optimisation stuff is finally sorted out later on...