X-Git-Url: http://git.megacz.com/?a=blobdiff_plain;f=ghc%2Fdriver%2Fghc.lprl;h=965a8d6d1940576665b20cc75f55cc874688828b;hb=67fe852eb2e9b3a489b62cbf9259b5a868db5468;hp=6296b9162e3093c31acbe045f926ad2d018fd118;hpb=5ef7da46260fb70ec63af2361c81512289bad02e;p=ghc-hetmet.git diff --git a/ghc/driver/ghc.lprl b/ghc/driver/ghc.lprl index 6296b91..965a8d6 100644 --- a/ghc/driver/ghc.lprl +++ b/ghc/driver/ghc.lprl @@ -1,4 +1,3 @@ -% % (c) The GRASP/AQUA Project, Glasgow University, 1992-1997 % @@ -99,7 +98,9 @@ INSTALLING HOSTPLATFORM TARGETPLATFORM -ProjectName ProjectVersion ProjectVersionInt ProjectPatchLevel +ProjectName ProjectVersion ProjectVersionInt + +HscMajorVersion HscMinorVersion CcMajorVersion CcMinorVersion TOP_PWD @@ -107,18 +108,20 @@ bindir libdir libexecdir datadir CURRENT_DIR TMPDIR -GHC_LIB_DIR GHC_RUNTIME_DIR GHC_UTILS_DIR GHC_INCLUDE_DIR +GHC_LIB_DIR GHC_RUNTIME_DIR GHC_INCLUDE_DIR GHC_OPT_HILEV_ASM GhcWithNativeCodeGen -GHC_UNLIT GHC_HSCPP GHC_HSC GHC_SYSMAN +GHC_UNLIT GHC_HSCPP GHC_MKDEPENDHS GHC_HSC GHC_SYSMAN CP RM CONTEXT_DIFF -WAY_*_NAME WAY_*_HC_OPTS +WAY_*_NAME WAY_*_REAL_OPTS LeadingUnderscore +GhcWithRegisterised + \end{verbatim} Establish what executables to run for the various phases, what the @@ -194,7 +197,6 @@ $HsCpp = # but this is re-set to "cat" (after options) if -cpp not seen : "$TopPwd/${CURRENT_DIR}/${GHC_HSCPP}"; @HsCpp_flags = (); -$genSPECS_flag = ''; # See ../utils/hscpp/hscpp.prl $HsC = ( $INSTALLING ) ? "$InstLibExecDirGhc/hsc" : "$TopPwd/${CURRENT_DIR}/${GHC_HSC}"; @@ -221,19 +223,13 @@ 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 = '-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 = ''; + $Oopt_UsageSPInf = ''; # Off by default } # end of setupOptFlags # Assign defaults to these right away. @@ -241,9 +237,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,15 +251,16 @@ $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 = (); +@Dll_flags = (); # 'nm' is used for consistency checking (ToDo: mk-world-ify) # ToDo: check the OS or something ("alpha" is surely not the crucial question) @@ -278,14 +279,17 @@ these are turned off by -Wnot. \begin{code} @StandardWarnings = ('-fwarn-overlapping-patterns', '-fwarn-missing-methods', + '-fwarn-missing-fields', '-fwarn-duplicate-exports'); @MinusWOpts = (@StandardWarnings, - '-fwarn-incomplete-patterns', '-fwarn-unused-binds', + '-fwarn-unused-matches', + '-fwarn-incomplete-patterns', '-fwarn-unused-imports'); @MinusWallOpts = (@MinusWOpts, - '-fwarn-unused-matches', - '-fwarn-name-shadowing'); + '-fwarn-type-defaults', + '-fwarn-name-shadowing', + '-fwarn-missing-signatures'); \end{code} What options \tr{-user-setup-a} turn into (user-defined ``packages'' @@ -296,18 +300,12 @@ Prelude ({\em including} its interface file(s)). $BuildTag = ''; # default is sequential build w/ Appel-style GC %BuildDescr = (# system ways begin - '', 'normal sequential', - '_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", + '', 'Normal Sequential', + '_p', "Profiling", + '_t', "Ticky-ticky Profiling", + '_u', "Unregisterised", + '_mp', "Parallel", + '_mg', "Gransim", # system ways end '_a', "$WAY_a_NAME", '_b', "$WAY_b_NAME", @@ -331,45 +329,30 @@ $BuildTag = ''; # default is sequential build w/ Appel-style GC # %SetupOpts = ( - '_a', "$WAY_a_HC_OPTS", - '_b', "$WAY_b_HC_OPTS", - '_c', "$WAY_c_HC_OPTS", - '_d', "$WAY_d_HC_OPTS", - '_e', "$WAY_e_HC_OPTS", - '_f', "$WAY_f_HC_OPTS", - '_g', "$WAY_g_HC_OPTS", - '_h', "$WAY_h_HC_OPTS", - '_i', "$WAY_i_HC_OPTS", - '_j', "$WAY_j_HC_OPTS", - '_k', "$WAY_k_HC_OPTS", - '_l', "$WAY_l_HC_OPTS", - '_m', "$WAY_m_HC_OPTS", - '_n', "$WAY_n_HC_OPTS", - '_o', "$WAY_o_HC_OPTS", - '_A', "$WAY_A_HC_OPTS", - '_B', "$WAY_B_HC_OPTS", + '_a', "$WAY_a_REAL_OPTS", + '_b', "$WAY_b_REAL_OPTS", + '_c', "$WAY_c_REAL_OPTS", + '_d', "$WAY_d_REAL_OPTS", + '_e', "$WAY_e_REAL_OPTS", + '_f', "$WAY_f_REAL_OPTS", + '_g', "$WAY_g_REAL_OPTS", + '_h', "$WAY_h_REAL_OPTS", + '_i', "$WAY_i_REAL_OPTS", + '_j', "$WAY_j_REAL_OPTS", + '_k', "$WAY_k_REAL_OPTS", + '_l', "$WAY_l_REAL_OPTS", + '_m', "$WAY_m_REAL_OPTS", + '_n', "$WAY_n_REAL_OPTS", + '_o', "$WAY_o_REAL_OPTS", + '_A', "$WAY_A_REAL_OPTS", + '_B', "$WAY_B_REAL_OPTS", # system ways - '_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" ); - -\end{code} - -Import/include directories (\tr{-I} options) are sufficiently weird to -require special handling. - -\begin{code} -@Import_dir = ('.'); #-i things -@Include_dir = ('.'); #-I things; other default(s) stuck on AFTER option processing + '_p', "-fscc-profiling -DPROFILING -optc-DPROFILING", + '_t', "-fticky-ticky -DTICKY_TICKY -optc-DTICKY_TICKY", + '_u', "-optc-DNO_REGS -optc-DUSE_MINIINTERPRETER -fno-asm-mangling -funregisterised", + '_mp', "-fstack-check -fparallel -D__PARALLEL_HASKELL__ -optc-DPAR", + '_mg', "-fstack-check -fconcurrent -fgransim -D__GRANSIM__ -D__CONCURRENT_HASKELL__ -optc-DCONCURRENT -optc-DGRAN"); # where to look for interface files (system hi's, i.e., prelude and syslibs) @SysImport_dir = ( $INSTALLING ) @@ -379,12 +362,19 @@ require special handling. # 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 = $ProjectVersionInt; -$Haskell1Version = 4; # i.e., Haskell 1.4 +$Haskell1Version = 5; # i.e., Haskell 1.4 @Cpp_define = (); -@UserLibrary_dir= (); #-L things;... -@UserLibrary = (); #-l things asked for by the user +# Cpp symbols defined when we're processing Haskell source. + +@HsSourceCppOpts = + ( "-D__HASKELL__=98" + , "-D__HASKELL1__=$Haskell1Version" + , "-D__GLASGOW_HASKELL__=$ProjectVersionInt" + , "-D__HASKELL98__" + , "-D__CONCURRENT_HASKELL__" + ); + @SysLibrary_dir = ( ( $INSTALLING ) #-syslib things supplied by the system ? $InstLibDirGhc @@ -394,16 +384,11 @@ $Haskell1Version = 4; # i.e., Haskell 1.4 , "$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"; # make depend for Haskell $MkDependHS - = ( $INSTALLING ) ? "$InstBinDirGhc/mkdependHS" - : "$TopPwd/$CURRENT_DIR/$GHC_UTILS_DIR/mkdependHS/mkdependHS"; + = ( $INSTALLING ) ? "$InstLibExecDirGhc/mkdependHS" + : "$TopPwd/$CURRENT_DIR/$GHC_MKDEPENDHS"; # Fill in later @MkDependHS_flags = (); @@ -422,8 +407,6 @@ sub initDriverGlobals { # reset the following options: # RTS flags to use while compiling @HsC_rts_flags = (); -@HsP_flags = (); # these are the flags destined solely for - # the flex/yacc parser @HsC_flags = (); @HsC_antiflags = (); \end{code} @@ -436,20 +419,19 @@ $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 = ''; +$USPLint = ''; $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 = (); - +# The SplitMarker is the string/character used to mark end of element +# in import lists. +$SplitMarker = ':'; @Import_dir = ('.'); #-i things @Include_dir = ('.'); #-I things; other default(s) stuck on AFTER option processing +@UserLibrary_dir= (); #-L things;... +@UserLibrary = (); #-l things asked for by the user +@SysLibrary = (); # will be built up as we go along \end{code} We are given a list of files with various presumably-known suffixes @@ -464,15 +446,21 @@ Here are the initial defaults applied to all files: $Cpp_flag_set = 0; # (hack) $Only_preprocess_C = 0; # pretty hackish $Only_preprocess_hc = 0; # ditto -$Only_generate_deps = 0; # " +$Only_generate_deps = 0; # "" +$Only_generate_dll = 0; $PostprocessCcOutput = 0; +# Win32 only: +# static = 0 => produce code for DLLs (when compiling & linking.) +$Static = 1; +$Static = 0 if ($EnableWin32DLLs eq 'YES'); + # 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)-/; + if ($HaveNativeCodeGen ne 'YES') && $TargetPlatform =~ /^(alpha)-/; +# TEMP: disable x86 & Sparc if $HaveNativeCodeGen && $TargetPlatform =~ /^(i386|alpha|sparc)-/; $ProduceHi = '-hifile='; $HiOnStdout = 0; $HiWith = ''; @@ -486,13 +474,13 @@ $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 +$PROFdict = ''; # set to relevant hsc flag if -auto-dicts $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 +$UNREGing = ($GhcWithRegisterised eq 'YES') ? '' : 'u'; $Specific_hi_file = ''; # set by -ohi ; "-" for stdout $Specific_dump_file = ''; # set by -odump ; "-" for stdout $Using_dump_file = 0; @@ -500,6 +488,7 @@ $Isuffix = ''; $Osuffix = ''; # default: use the normal suffix for that kind of output $HiSuffix = 'hi'; $HiSuffix_prelude = ''; +$CompilingPrelude=0; $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; @@ -508,12 +497,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) @@ -541,14 +533,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 = 33; -$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: @@ -577,16 +569,22 @@ if ( $Status == 0 && $Only_generate_deps ) { push (@MkDependHS_flags, "-o$Osuffix") if $Osuffix; push (@MkDependHS_flags, "-s$BuildTag") if $BuildTag; - push (@MkDependHS_flags, "-D__HASKELL1__=$Haskell1Version"); # 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 -- @Cmd_opts -- @Input_file" ; + local($to_do) = "$MkDependHS @MkDependHS_flags @HsSourceCppOpts -- @Cmd_opts -- @Input_file" ; &run_something($to_do, 'Haskell dependencies'); exit $Status; } +# ..or just to construct a (Haskell) DLL. +if ( $Status == 0 && $Only_generate_dll && $EnableWin32DLLs ) { + + &createWin32DLL(); + exit $Status; +} + # if there are several input files, # we don't allow \tr{-o } or \tr{-ohi } options... # (except if linking, of course) @@ -684,198 +682,104 @@ It really really wants to be the last STG-to-STG pass that is run. 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... - $Oopt_PedanticBottoms, -# $Oopt_MonadEtaExpansion, # no thanks - -# These two work fine, if you really want no simplification at all, -# for bizarre test reasons. But you get really terrible code if you use them, -# for example: let x = e in x -# with dozens of redundant thunks etc. So I'm leaving them out. -# -# '-fsimpl-uf-use-threshold0', -# '-fessential-unfoldings-only', + # this pass-ordering sequence was agreed by Simon and Andr\'e + # (WDP 94/07, 94/11). - $Oopt_UnfoldingUseThreshold, - $Oopt_MaxSimplifierIterations, - $Oopt_ShowSimplifierProgress, + @HsC_minusNoO_flags + = ( + '-fsimplify', + '[', + '-finline-phase2', + $Oopt_MaxSimplifierIterations, ']', + $Oopt_AddAutoSccs, -# '-ffull-laziness', # removed 95/04 WDP following Andr\'e's lead - $Oopt_FinalStgProfilingMassage ); @HsC_minusO_flags # NOTE: used for *both* -O and -O2 (some conditional bits) = ( + '-ffoldr-build-on', + '-fdo-eta-reduction', + '-fdo-lambda-eta-expansion', + '-fcase-of-case', + '-fcase-merge', + '-flet-to-case', + $Oopt_PedanticBottoms, # initial simplify: mk specialiser happy: minimum effort please + '-fsimplify', '[', - $Oopt_FB_Support, - '-fkeep-spec-pragma-ids', # required before specialisation - -# I don't understand why we want -fessential-unfoldings-only here -# If we have it, the following nasty thing happens: -# f = E -# g* = f -# ...g... -# where "*" means exported. -# In the essential-unfoldings pass we still substitute f for g -# but we don't substitute E for f first. So we get -# f = E -# g* = f -# ...f... -# The g=f will get reverse-substituted later, but it's untidy. -# -# '-fessential-unfoldings-only', -# '-fsimpl-uf-use-threshold0', - - '-fmax-simplifier-iterations1', - $Oopt_PedanticBottoms, + '-finline-phase0', # Don't inline anything till full laziness has bitten + # In particular, inlining wrappers inhibits floating + # e.g. ...(case f x of ...)... + # ==> ...(case (case x of I# x# -> fw x#) of ...)... + # ==> ...(case x of I# x# -> case fw x# of ...)... + # and now the redex (f x) isn't floatable any more + '-fmax-simplifier-iterations2', ']', - ($Oopt_DoSpecialise) ? ( - '-fspecialise-overloaded', - $Oopt_SpecialiseUnboxed, - $Oopt_DoSpecialise, - ) : (), - - '-fsimplify', # need dependency anal after specialiser ... - '[', # need tossing before calc-inlinings ... - $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', - $Oopt_PedanticBottoms, - $Oopt_MonadEtaExpansion, - $Oopt_UnfoldingUseThreshold, - $Oopt_MaxSimplifierIterations, - $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', - ']', + # Specialisation is best done before full laziness + # so that overloaded functions have all their dictionary lambdas manifest + ($Oopt_DoSpecialise) ? ( $Oopt_DoSpecialise, ) : (), + '-ffull-laziness', + '-ffloat-inwards', -#LATER: '-fcalc-inlinings1', -- pointless for 2.01 - -# ($Oopt_FoldrBuildWW) ? ( -# '-ffoldr-build-ww-anal', -# '-ffoldr-build-worker-wrapper', -# '-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', -# $Oopt_PedanticBottoms, -# $Oopt_MonadEtaExpansion, -# $Oopt_UnfoldingUseThreshold, -# $Oopt_MaxSimplifierIterations, -# $Oopt_ShowSimplifierProgress, -# ']', -# ) : (), +# '-fsimplify', +# '[', +# # Run the simplifier before specialising, so that overloaded functions +# # look like f = \d -> ... +# # (Full laziness may lift out something hiding the \d +# '-finline-phase1', +# '-fmax-simplifier-iterations1', +# ']', - # this pass-ordering sequence was agreed by Simon and Andr\'e - # (WDP 94/07, 94/11). - '-ffull-laziness', - ($Oopt_FoldrBuild) ? ( - '-ffoldr-build-on', # desugar list comprehensions for foldr/build - - '-fsimplify', - '[', - '-fignore-inline-pragma', # **** NB! - '-fdo-foldr-build', # NB - $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', # After full laziness - '-freuse-con', - $Oopt_PedanticBottoms, - $Oopt_MonadEtaExpansion, - $Oopt_UnfoldingUseThreshold, - $Oopt_MaxSimplifierIterations, - $Oopt_ShowSimplifierProgress, - ']', - ) : (), + '-fsimplify', + '[', + '-finline-phase1', + # Want to run with inline phase 1 after the specialiser to give + # maximum chance for fusion to work before we inline build/augment + # in phase 2. This made a difference in 'ansi' where an overloaded + # function wasn't inlined till too late. + $Oopt_MaxSimplifierIterations, + ']', - '-ffloat-inwards', + $Oopt_UsageSPInf, # infer usage information here in case we need it later. + # (add more of these where you need them --KSW 1999-04) '-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', - ($Oopt_FoldrBuildInline), - # 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_ShowSimplifierProgress, + # Need inline-phase2 here so that build/augment get + # inlined. I found that spectral/hartel/genfft lost some useful + # strictness in the function sumcode' if augment is not inlined + # before strictness analysis runs + + '-finline-phase2', + $Oopt_MaxSimplifierIterations, ']', + '-fstrictness', + '-fcpr-analyse', + '-fworker-wrapper', '-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', # Aha! Only done after strictness analysis - $Oopt_PedanticBottoms, - $Oopt_MonadEtaExpansion, - $Oopt_UnfoldingUseThreshold, - $Oopt_MaxSimplifierIterations, - $Oopt_ShowSimplifierProgress, + $Oopt_MaxSimplifierIterations, + # No -finline-phase: allow all Ids to be inlined now ']', + '-fcse', # CSE must immediately follow a simplification pass, because it relies + # on the no-shadowing invariant. See comments at the top of CSE.lhs + + '-ffull-laziness', # nofib/spectral/hartel/wang doubles in speed if you + # do full laziness late in the day. It only happens + # after fusion and other stuff, so the early pass doesn't + # catch it. For the record, the redex is + # f_el22 (f_el21 r_midblock) '-ffloat-inwards', # Case-liberation for -O2. This should be after @@ -883,39 +787,20 @@ 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 $Oopt_ShowSimplifierProgress ]" ), +# : "-fliberate-case -fsimplify [ $Oopt_FB_Support -ffloat-lets-exposing-whnf -ffloat-primops-ok -fcase-of-case -fdo-case-elim -fcase-merge -fdo-lambda-eta-expansion -freuse-con -flet-to-case $Oopt_PedanticBottoms $Oopt_MaxSimplifierIterations $Oopt_ShowSimplifierProgress ]" ), # Final clean-up simplification: '-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', - '-fignore-inline-pragma', # **** NB! - $Oopt_FoldrBuildInline, - ($Oopt_FoldrBuild) ? ('-fdo-foldr-build') : (), - # but still do reductions if you see them! - $Oopt_PedanticBottoms, - $Oopt_MonadEtaExpansion, - $Oopt_UnfoldingUseThreshold, - $Oopt_MaxSimplifierIterations, - $Oopt_ShowSimplifierProgress, + $Oopt_MaxSimplifierIterations, + # No -finline-phase: allow all Ids to be inlined now ']', # '-fstatic-args', -#LATER: '-fcalc-inlinings2', -- pointless for 2.01 - # stg2stg passes - '-flambda-lift', +# '-flambda-lift', $Oopt_FinalStgProfilingMassage, $Oopt_StgStats, @@ -949,8 +834,7 @@ 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... @@ -970,43 +854,29 @@ if ( $OptLevel <= 0 ) { %* * %************************************************************************ -Sort out @$BuildTag@, @$PROFing@, @$CONCURing@, @$PARing@, -@$GRANing@, @$TICKYing@: +Sort out @$BuildTag@, @$PROFing@, @$PARing@, +@$GRANing@, @$TICKYing@, @UNREGing@: \begin{code} sub setupBuildFlags { # PROFILING stuff after argv mangling: if ( ! $PROFing ) { - # warn about any scc exprs found (in case scc used as identifier) - push(@HsP_flags, '-W'); - # 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; - #push(@HsC_flags, $PROFdict) if $PROFdict; + push(@HsC_flags, $PROFdict) if $PROFdict; $Oopt_FinalStgProfilingMassage = '-fmassage-stg-for-profiling'; # Ignore user sccs when auto annotating, but warn when doing so. $PROFignore_scc = '-W' if $PROFauto; - - push(@HsP_flags, (($PROFignore_scc) ? $PROFignore_scc : '-S')); - - 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++; - } } #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; } @@ -1019,13 +889,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; } @@ -1043,8 +907,12 @@ sub setupBuildFlags { } elsif ( $TICKYing eq 't' ) { $BuildTag = '_t'; - } + } elsif ( $UNREGing eq 'u' ) { + if ($GhcWithRegisterised eq 'YES') { + $BuildTag = '_u'; + } + } \end{code} After the sanity checks, add flags to the necessary parts of the driver pipeline: @@ -1071,14 +939,17 @@ Decide what the consistency-checking options are in force for this run: # Funny place to put it, but why not. # if ( $HiSuffix_prelude eq '' ) { - local($Tag) = "${BuildTag}"; - $Tag =~ s/_//; - $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}"); + if ($CompilingPrelude) { + $HiSuffix_prelude = "$HiSuffix" if $CompilingPrelude; + } else { + local($Tag) = "${BuildTag}"; + + $Tag =~ s/_//; + $Tag = "${Tag}_" if $Tag ne ''; + $HiSuffix_prelude="${Tag}hi"; + } + } } # setupBuildFlags \end{code} @@ -1098,14 +969,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 @@ -1120,31 +986,18 @@ 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"); + + unshift(@CcBoth_flags, ('-DDONT_WANT_WIN32_DLL_SUPPORT')) if ($Static); } 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! @@ -1161,22 +1014,12 @@ 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; unshift(@CcBoth_flags, ('-static')); # always easier to start with unshift(@CcRegd_flags, ('-finhibit-size-directive')); # avoids traceback tables } 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} @@ -1211,20 +1054,44 @@ 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}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" + ,'-u', "${uscore}PrelException_stackOverflow_closure" + ,'-u', "${uscore}PrelException_heapOverflow_closure" + ,'-u', "${uscore}PrelException_NonTermination_static_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 \end{code} @@ -1261,23 +1128,23 @@ 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 =~ /-(mingw32|cygwin32)$/); + # Note: currently only tested with mingw, may cause conflicts when linking + # with libcygwin.a + push(@SysLibrary, '-lwsock32') if ($TargetPlatform =~ /-(mingw32|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' ) { @@ -1286,8 +1153,17 @@ sub setupSyslibs { } # Push the GNU multi-precision arith lib; and the math library -push(@SysLibrary, '-lgmp'); -push(@SysLibrary, '-lm'); + +# 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') if !( $TargetPlatform =~ /^.*(cygwin32|mingw32)$/ ); \end{code} %************************************************************************ @@ -1347,8 +1223,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" - if $Verbose; +print STDERR "${ProjectName}, version ${ProjectVersion}\n" if $Verbose; \end{code} %************************************************************************ @@ -1364,135 +1239,15 @@ foreach $ifile (@Input_file) { &ProcessInputFile($ifile); } -if ( $Status > 0 ) { # don't link if there were errors... +# don't link if there were errors... +if ( $Status > 0 ) { print STDERR $ShortUsage; &tidy_up(); exit $Status; } -# append last minute flags linker and consistency flags -&setupBuildFlags(); -&setupSyslibs(); -&setupLinkOpts(); - -\end{code} - -Link if appropriate. -\begin{code} -if ($Do_lnkr) { - local($libdirs) = ''; - - # glue them together: - push(@UserLibrary_dir, @SysLibrary_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 : $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'; - - local($to_do) = "$lnkr $Verbose @Ld_flags $output @Link_file $TopClosureFile $libdirs @UserLibrary @SysLibrary"; - &run_something($to_do, 'Linker'); - - # finally, check the consistency info in the binary - local($executable) = $Files_to_tidy[0]; - @Files_to_tidy = (); # reset; we don't want to nuke it if it's inconsistent - - if ( $LinkChk ) { - # dynamically load consistency-chking code; then do it. - require('ghc-consist.prl') - || &tidy_up_and_die(1,"$Pgm: panic: can't load ghc-consist.prl!\n"); - - &chk_consistency_info ( $executable ); - } - - # if PVM parallel stuff, we do truly weird things. - # Essentially: (1) move the executable over to where PVM expects - # to find it. (2) create a script in place of the executable - # which will cause the program to be run, via SysMan. - if ( $PARing eq 'p' ) { - local($pvm_executable) = $executable; - local($pvm_executable_base); - - if ( $pvm_executable !~ /^\// ) { # a relative path name: make absolute - local($pwd) = `pwd`; - chop($pwd); - $pwd =~ s/^\/tmp_mnt//; - $pvm_executable = "$pwd/$pvm_executable"; - } - - $pvm_executable =~ s|/|=|g; # make /s into =s - $pvm_executable_base = $pvm_executable; - - $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'); - - # OK, now create the magic script for "$executable" - open(EXEC, "> $executable") || &tidy_up_and_die(1,"$Pgm: couldn't open $executable to write!\n"); - print EXEC <"@. @@ -1688,7 +1452,32 @@ 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("rm -f $ofile_c_stub_target && echo '#include \"${ofile_h_stub_target}\"' > $ofile_c_stub_target && cat $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/; + if ($do_cc) { + &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) { @@ -1710,8 +1499,7 @@ Finally, decide what to queue up for linker input. #ToDo: local($or_isuf) = ($Isuffix eq '') ? '' : "|$Isuffix"; - - if ( $ifile !~ /\.(lhs|hs|hc|c|s|a)$/ && $ifile !~ /_hc$/ ) { + 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$/ ) { @@ -1769,7 +1557,7 @@ sub runHscpp { &run_something($to_do, 'Ineffective C pre-processor'); } else { local($includes) = '-I' . join(' -I',@Include_dir); - $to_do .= "$HsCpp $Verbose $genSPECS_flag @HsCpp_flags -D__HASKELL1__=$Haskell1Version -D__GLASGOW_HASKELL__=$GhcVersionInfo $includes $lit2pgm_hscpp >> $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'); } @@ -1785,7 +1573,9 @@ sub runHscpp { \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 @@ -1824,15 +1614,22 @@ sub runHscAndProcessInterfaces { $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) { push(@HsC_flags, '-fsource-unchanged'); } + # Indicate whether we're static or not. + # This will only ever + push(@HsC_flags, '-static') if $Static; + # 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 @@ -1905,29 +1702,26 @@ sub runHscAndProcessInterfaces { \begin{code} sub runHsc { - local($ifile_root, $hsc_out, $hsc_hi, $going_interactive) = @_; - - # prepend comma to HsP flags (so hsc can tell them apart...) - foreach $a ( @HsP_flags ) { $a = ",$a" unless $a =~ /^,/; } + local($ifile_root, $hsc_out, $hsc_hi, $hsc_out_c_stub, $hsc_out_h_stub, $going_interactive) = @_; &makeHiMap() unless $HiMapDone; - #print STDERR "HiIncludes: $HiIncludeString\n"; - push(@HsC_flags, "-himap=$HiIncludeString"); + push(@HsC_flags, "\"-himap=$HiIncludeString\""); + push(@HsC_flags, "\"-himap-sep=${SplitMarker}\""); # here, we may produce .hc/.s and/or .hi files local($output) = ''; #@Files_to_tidy = (); if ( $going_interactive ) { - # don't need .hi unless going to show it on stdout: - $ProduceHi = '-nohifile=' if ! $HiOnStdout; + # don't need .hi unless we're going to show it on stdout: + $ProduceHi = '-nohifile=' if ! ($HiOnStdout || $Specific_hi_file ne '' ); $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"; - push(@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 ) { @@ -1939,7 +1733,7 @@ sub runHsc { # 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(@HsC_rts_flags, "-S$Tmp_prefix.stat"); push(@Files_to_tidy, "$Tmp_prefix.stat"); } @@ -1950,7 +1744,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 $USPLint $StgLint $Verbose"; + close(OPTS); + $to_do = "$HsC $hscpp_hsc \@$Tmp_prefix.opts $output +RTS @HsC_rts_flags"; + + } else { + + $to_do = "$HsC $hscpp_hsc $dump @HsC_flags $CoreLint $USPLint $StgLint $Verbose $output +RTS @HsC_rts_flags"; + } &run_something($to_do, 'Haskell compiler'); # finish business w/ nofibbish time/bytes-alloc stats @@ -1976,7 +1791,7 @@ sub makeHiMap { foreach $d ( @Import_dir ) { if ($HiIncludeString) { - $HiIncludeString = "$HiIncludeString:${d}%.${HiSuffix}"; + $HiIncludeString = "$HiIncludeString${SplitMarker}${d}%.${HiSuffix}"; } else { $HiIncludeString = "$d%.${HiSuffix}"; } @@ -1985,7 +1800,7 @@ sub makeHiMap { foreach $d ( @SysImport_dir ) { if ($HiIncludeString) { - $HiIncludeString = "$HiIncludeString:${d}%.${HiSuffix_prelude}"; + $HiIncludeString = "$HiIncludeString${SplitMarker}${d}%.${HiSuffix_prelude}"; } else { $HiIncludeString = "${d}%.${HiSuffix_prelude}"; } @@ -1996,6 +1811,208 @@ sub makeHiMap { \end{code} +Invoke the 'linker' - either the standard linker or the one used to build +a (Win32) DLL. + +\begin{code} +sub runLinker +{ + local($libdirs) = ''; + + # append last minute flags linker and consistency flags + &setupBuildFlags(); + &setupSyslibs(); + &setupLinkOpts(); + + # glue them together: + push(@UserLibrary_dir, @SysLibrary_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 : $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'; + + &prepareWin32DllLink(1); + + local($to_do) = "$lnkr $Verbose @Ld_flags $output @Link_file $libdirs @UserLibrary @SysLibrary"; + &run_something($to_do, 'Linker'); + + # finally, check the consistency info in the binary + local($executable) = $Files_to_tidy[0]; + @Files_to_tidy = (); # reset; we don't want to nuke it if it's inconsistent + + if ( $LinkChk ) { + # dynamically load consistency-chking code; then do it. + require('ghc-consist.prl') + || &tidy_up_and_die(1,"$Pgm: panic: can't load ghc-consist.prl!\n"); + + &chk_consistency_info ( $executable ); + } + + # if PVM parallel stuff, we do truly weird things. + # Essentially: (1) move the executable over to where PVM expects + # to find it. (2) create a script in place of the executable + # which will cause the program to be run, via SysMan. + if ( $PARing eq 'p' ) { + local($pvm_executable) = $executable; + local($pvm_executable_base); + + if ( $pvm_executable !~ /^\// ) { # a relative path name: make absolute + local($pwd) = `pwd`; + chop($pwd); + $pwd =~ s/^\/tmp_mnt//; + $pvm_executable = "$pwd/$pvm_executable"; + } + + $pvm_executable =~ s|/|=|g; # make /s into =s + $pvm_executable_base = $pvm_executable; + + $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'); + + # OK, now create the magic script for "$executable" + open(EXEC, "> $executable") || &tidy_up_and_die(1,"$Pgm: couldn't open $executable to write!\n"); + print EXEC <= 0; + + &prepareWin32DllLink(0); + + local ($bld_dll) = "dllwrap"; + + local ($output) = ($Specific_output_file ne '') ? "$Specific_output_file" : 'HSdll.dll'; + local ($output_dir); + local ($output_file); + local ($output_lib, $output_def); + + ($output_dir = $output) =~ s|(.*/)[^/]+$|$1|; + $output_dir = "" if ($output_dir eq $output); + ($output_file = $output) =~ s|.*/([^/]+)$|$1|; + + ($output_lib = $output_file) =~ s|(.+)\.[^\.]*$|${output_dir}lib$1_imp.a|; + ($output_def = $output_file) =~ s|(.+)\.[^\.]*$|${output_dir}$1.def|; + + push (@Dll_flags, "-mno-cygwin --target=i386-mingw32") if ($TargetPlatform =~ /^.*mingw32$/); + push (@Dll_flags, "--output-lib $output_lib"); + # If the "--def " option hasn't been supplied, assume everything + # is going to be exported via the DLL.." + if (!grep(/--def/, @Dll_flags)) { + push (@Dll_flags, "--export-all --output-def $output_def"); + } + + local($to_do) = "$bld_dll @Dll_flags -o $output @Link_file $libdirs @UserLibrary @SysLibrary"; + # Make sure the user sees this piece of magic. + print STDERR "$to_do\n" if (!$Verbose); + &run_something($to_do, 'DLL creator'); +} + +sub prepareWin32DllLink +{ + local($linking_main) = @_; + + # + # Win32 DLLs - link with import libraries, not the real archives. + # + if ( $TargetPlatform =~ /-mingw32$/ ) { + if (!$Static) { + # + # If the libraries have the form libHSfoo.a, we + # transform that into libHSfoo_imp.a - the import + # library of the DLL. + # + foreach $a ( @SysLibrary ) { + $a = "${a}_imp" if ($a =~ /^-lHS/); + } + foreach $a ( @UserLibrary ) { + $a = "${a}_imp" if ($a =~ /^-lHS/); + } + push(@Link_file, ( $INSTALLING ) ? "$InstLibDirGhc/Main.dll_o" + : "$TopPwd/$CURRENT_DIR/$GHC_RUNTIME_DIR/Main.dll_o") if $linking_main; + push(@Link_file, ( $INSTALLING ) ? "$InstLibDirGhc/PrelMain.dll_o" + : "$TopPwd/$CURRENT_DIR/$GHC_LIB_DIR/std/PrelMain.dll_o") if $linking_main; + } + push(@Ld_flags, "-mno-cygwin"); + } +} +\end{code} + + %************************************************************************ %* * \section[Driver-misc-utils]{Miscellaneous utilities} @@ -2037,13 +2054,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"; @@ -2052,27 +2071,24 @@ 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"); # 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 -D__HASKELL1__=$Haskell1Version $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 )"; - # note: __GLASGOW_HASKELL__ is pointedly *not* #defined at the C level. + 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; @@ -2092,38 +2108,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') @@ -2135,11 +2128,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... @@ -2155,8 +2143,11 @@ 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"; + 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'); @@ -2235,16 +2226,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/; @@ -2257,7 +2242,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; @@ -2283,7 +2267,7 @@ sub process_ghc_timings { local($tot_samples) = 0; while () { - if (! /Minor/ && /^\s*\d+\s+\d+\s+(\d+)\s+\d+\.\d+\%/ ) { + 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; @@ -2294,7 +2278,11 @@ sub process_ghc_timings { $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+([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' @@ -2341,7 +2329,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 @@ -2442,23 +2430,212 @@ 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 concurrent' # 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 + ], + com, + [ # where to slurp interface files from + ( $INSTALLING + ? "$InstLibDirGhc/imports/com" + : "$TopPwd/hdirect/lib" + ) + , # where to find the archive to use when linking + ( $INSTALLING + ? "$InstLibDirGhc" + : "$TopPwd/hdirect/lib" + ) + , '' + , 'exts' # Syslib dependencies + , '' # extra ghc opts + , '' # extra cc opts + , '-luser32 -lole32 -loleaut32 -ladvapi32' + # extra ld opts + ] + ); + + # check if it's supported.. - unshift(@SysImport_dir, - $INSTALLING ? "$InstLibDirGhc/imports/$syslib" - : "$TopPwd/$CURRENT_DIR/$GHC_LIB_DIR/$syslib"); + 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; - push(@SysLibrary_dir, - $INSTALLING ? ("$InstLibDirGhc") - : ("$TopPwd/$CURRENT_DIR/$GHC_LIB_DIR/$syslib", - "$TopPwd/$CURRENT_DIR/$GHC_LIB_DIR/$syslib/cbits")); + 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") - unless $syslib eq 'contrib' || $syslib eq 'exts' || $syslib eq 'concurrent'; - #HACK! they have no cbits + 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} @@ -2486,7 +2663,7 @@ sub check_for_source_options { open(FILE,$file) || return(1); # No big loss while () { - if ( /^${comment_start} OPTIONS (.*)${comment_end}$/ ) { + if ( /^${comment_start} OPTIONS (.*)${comment_end}/ ) { # add the options found at the back of the command line. local(@entries) = split(/\s+/,$1); print STDERR "Found OPTIONS " . join(' ',@entries) . " in $file\n" if $Verbose; @@ -2528,7 +2705,7 @@ sub splitCmdLine { arg: while($_ = $args[0]) { shift(@args); # sigh, we have to deal with these -option arg specially here. - /^-(tmpdir|odir|ohi|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; }; @@ -2592,7 +2769,7 @@ 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}\n"; exit $Status; }; #---------- verbosity and such ----------------------------------------- /^-v$/ && do { $Verbose = '-v'; $Time = 'time'; next arg; }; @@ -2635,6 +2812,8 @@ arg: while($_ = $Args[0]) { # stop after preprocessing C /^-M$/ && do { $Only_generate_deps = 1; $Do_as = 0; $Do_lnkr = 0; next arg; }; # only generate dependency information. + /^--mk-dll$/ && do { $Only_generate_dll = 1; $Do_as = 0; $Do_lnkr = 0; next arg; }; + # Build a Win32 DLL (where supported). /^-S$/ && do { $Do_as = 0; $Do_lnkr = 0; next arg; }; # stop after generating assembler @@ -2642,8 +2821,8 @@ arg: while($_ = $Args[0]) { # stop after generating .o files /^-link-chk$/ && do { $LinkChk = 1; next arg; }; - /^-no-link-chk$/ && do { $LinkChk = 0; next arg; }; # don't do consistency-checking after a link + /^-no-link-chk$/ && do { $LinkChk = 0; next arg; }; /^-tmpdir$/ && do { $Tmp_prefix = &grab_arg_arg(*Args,'-tmpdir', ''); $Tmp_prefix = "$Tmp_prefix/ghc$$"; @@ -2704,6 +2883,7 @@ arg: while($_ = $Args[0]) { $Status++; } } + $ProduceHi='-hifile='; next arg; }; # The suffix to use when looking for interface files @@ -2713,13 +2893,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; @@ -2734,13 +2907,14 @@ arg: while($_ = $Args[0]) { /^-prof$/ && do { $PROFing = 'p'; next arg; }; # profiling -- details later! - /^-auto/ && do { - # generate auto SCCs on top level bindings - # -auto-all = all top level bindings - # -auto = only top level exported bindings - $PROFauto = ( /-all/ ) - ? '-fauto-sccs-on-all-toplevs' - : '-fauto-sccs-on-exported-toplevs'; + /^-auto-dicts$/ && do { + $PROFdicts = '-fauto-sccs-on-dicts'; + next arg; }; + /^-auto-all$/ && do { + $PROFauto = '-fauto-sccs-on-all-toplevs'; + next arg; }; + /^-auto$/ && do { + $PROFauto = '-fauto-sccs-on-exported-toplevs'; next arg; }; /^-caf-all/ && do { # generate individual CAF SCC annotations @@ -2763,14 +2937,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'; &add_syslib('concurrent'); next arg; }; - # concurrent Haskell; implies -syslib conc - /^-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" -------------------------------------------- @@ -2796,8 +2968,16 @@ arg: while($_ = $Args[0]) { print STDERR "WARNING: import paths cleared by `-i'\n"; next arg; }; - /^-i(.*)/ && do { local(@new_items) - = split( /:/, &grab_arg_arg(*Args,'-i', $1)); + /^-i(.*)/ && do { local(@new_items); + local($arg) = $1; + + # + if ( $arg =~ /;/ ) { + $SplitMarker=";"; + @new_items = split( /;/, &grab_arg_arg(*Args,'-i', $arg)); + } else { + @new_items = split( /:/, &grab_arg_arg(*Args,'-i', $arg)); + } unshift(@Import_dir, @new_items); next arg; }; @@ -2806,24 +2986,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 =~ /^(exts|misc|posix)$/; - - # - # The posix library is a `special' in that it relies on - # the ghc system library (packed strings). Wielding our - # sledgehammer, the problem is solved by silently including - # the ghc system library as well. - # (ToDo: `nub' -syslib list) - # &add_syslib($syslib); - if ( $syslib eq 'posix' ) { - &add_syslib('misc'); - } elsif ( $syslib eq 'misc' && - $TargetName =~ /-solaris2$/ ) { - # needed for Berkeley socket/nwork stuff. - push(@SysLibrary, '-lnsl'); - } next arg; }; #======================================================================= @@ -2847,21 +3010,17 @@ 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; }; - /^-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; }; + /^-optdll(.*)$/ && do { push(@Dll_flags, $1); next arg; }; /^-optdep(.*)$/ && do { push(@MkDependHS_flags, $1); next arg; }; #---------- Haskell C pre-processor (hscpp) ---------------------------- /^-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; }; @@ -2871,28 +3030,24 @@ 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; }; + /^-fignore-asserts$/ && 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; }; - /^-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"; @@ -2908,50 +3063,42 @@ arg: while($_ = $Args[0]) { } next arg; }; + /^-unreg$/ && do { $UNREGing = 'u'; next arg; }; + /^-funregisterised$/ && do { push(@HsC_flags, $_); 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; }; + /^-fhistory-size.*$/ && do { push(@HsC_flags, $_); next arg; }; + /^-fdicts-strict$/ && 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$/ && do { $Oopt_DoSpecialise = ''; next arg; }; + /^-fusagesp$/ + && do { $Oopt_UsageSPInf = '-fusagesp'; + push (@HsC_flags, '-fusagesp-on'); next arg; }; + + /^-fcompiling-prelude$/ && do { $CompilingPrelude=1; push(@HsC_flags, $_); next arg; }; # Now the foldr/build options, which are *on* by default (for -O). /^-ffoldr-build$/ && do { $Oopt_FoldrBuild = 1; - $Oopt_FB_Support = '-fdo-arity-expand'; #print "Yes F/B\n"; next arg; }; /^-fno-foldr-build$/ && do { $Oopt_FoldrBuild = 0; - $Oopt_FB_Support = ''; - next arg; }; - - /^-fno-foldr-build-rule$/ - && do { $Oopt_FoldrBuild = 0; - next arg; }; - - /^-fno-enable-tech$/ - && do { $Oopt_FB_Support = ''; - next arg; }; - - /^-fno-snapback-to-append$/ - && do { $Oopt_FoldrBuildInline .= ' -fdo-not-fold-back-append '; next arg; }; # --------------- Renamer ------------- @@ -2967,46 +3114,30 @@ arg: while($_ = $Args[0]) { # --------------- - /^(-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); next arg; }; - /^(-fshow-simplifier-progress)/ - && do { $Oopt_ShowSimplifierProgress = $1; - next arg; }; /^-fno-pedantic-bottoms$/ && do { $Oopt_PedanticBottoms = ''; next arg; }; - /^-fdo-monad-eta-expansion$/ - && do { $Oopt_MonadEtaExpansion = $_; next arg; }; + /^-fno-pre-inlining$/ + && do { push(@HsC_flags, $_); 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; }; + /^-funbox-strict-fields$/ + && do { push(@HsC_flags, $_); next arg; }; # --------------- Warnings etc. ------ - /^-fshow-import-specs/ - && do { push(@HsC_flags, $_); next arg; }; - - /^-fsignatures-required/ - && do { push(@HsC_flags, $_); next arg; }; - /^-fwarn-(.*)$/ && do { push(@HsC_flags, $_); next arg; }; /^-fno-(.*)$/ && do { push(@HsC_antiflags, "-f$1"); @@ -3021,6 +3152,10 @@ arg: while($_ = $Args[0]) { 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, @@ -3043,6 +3178,9 @@ arg: while($_ = $Args[0]) { # -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; }; + # Ditto for USP lint + /^-dusagesp-lint/ && do { $USPLint = '-dusagesp-lint'; next arg; }; + /^-dno-usagesp-lint/ && do { $USPLint = ''; next arg; }; # Ditto for STG lint /^-dstg-lint/ && do { $StgLint = '-dstg-lint'; next arg; }; /^-dno-stg-lint/ && do { $StgLint = ''; next arg; }; @@ -3129,7 +3267,8 @@ arg: while($_ = $Args[0]) { #---------- Linker (gcc, really) --------------------------------------- - /^-static$/ && do { push(@Ld_flags, $_); next arg; }; + /^-static$/ && do { $Static=1; 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...