-%
% (c) The GRASP/AQUA Project, Glasgow University, 1992-1997
%
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)
-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.
HOSTPLATFORM TARGETPLATFORM
-PROJECTNAME PROJECTVERSION PROJECTPATCHLEVEL
+ProjectName ProjectVersion ProjectVersionInt ProjectPatchLevel
+
+HscMajorVersion HscMinorVersion CcMajorVersion CcMinorVersion
TOP_PWD
-bindir libdir datadir
+bindir libdir libexecdir datadir
CURRENT_DIR TMPDIR
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
$TargetPlatform = $TARGETPLATFORM;
-$TopPwd = "${TOP_PWD}";
-$InstBinDirGhc = "${bindir}";
-$InstLibDirGhc = "${libdir}";
-$InstDataDirGhc = "${datadir}";
-$InstSysLibDir = ( $INSTALLING ) ? "${InstLibDirGhc}/hslibs" : "$TopPwd/hslibs";
+$TopPwd = "${TOP_PWD}";
+$InstBinDirGhc = "${bindir}";
+$InstLibDirGhc = "${libdir}";
+#
+# Normally the same as InstLibDirGhc, but we accommodate
+# for it being separate.
+#
+$InstLibExecDirGhc = "${libexecdir}";
+$InstDataDirGhc = "${datadir}";
$Status = 0; # just used for exit() status
$Verbose = '';
$ENV{'TMPDIR'} = ${TMPDIR}; # set the env var as well
}
+# Some shells run into real trouble when command line and environment
+# gets big (e.g., cmd lines of >4K to /bin/sh causes havoc on our
+# Solaris-2.5.1 boxes - even though sysconf(_SC_ARG_MAX) reports 1M ...).
+# To work around any such */bin/sh* problems, we will scribble such
+# awfully long command lines into a temp file and exec that temp file
+# with $(REAL_SHELL) (don't use the SHELL variable directly as this
+# will normally get you the wrong thing when the driver is invoked
+# from within `make'). If the REAL_SHELL variable isn't set, you'll
+# get SHELL. This is all a terrible hack. (in case you hadn't reached
+# the same conclusion by now :-)
+#
+# TBC..
+#
+if ( ! $ENV{'REAL_SHELL'} ) {
+ $ENV{'REAL_SHELL'} = $ENV{'SHELL'};
+}
+
@Files_to_tidy = (); # files we nuke in the case of abnormal termination
-$Unlit = ( $INSTALLING ) ? "$InstLibDirGhc/unlit"
+$Unlit = ( $INSTALLING ) ? "$InstLibExecDirGhc/unlit"
: "$TopPwd/${CURRENT_DIR}/${GHC_UNLIT}";
$Cp = $CP;
$Time = '';
$HsCpp = # but this is re-set to "cat" (after options) if -cpp not seen
- ( $INSTALLING ) ? "$InstLibDirGhc/hscpp"
+ ( $INSTALLING ) ? "$InstLibExecDirGhc/hscpp"
: "$TopPwd/${CURRENT_DIR}/${GHC_HSCPP}";
@HsCpp_flags = ();
-$genSPECS_flag = ''; # See ../utils/hscpp/hscpp.prl
-$HsC = ( $INSTALLING ) ? "$InstLibDirGhc/hsc"
+$HsC = ( $INSTALLING ) ? "$InstLibExecDirGhc/hsc"
: "$TopPwd/${CURRENT_DIR}/${GHC_HSC}";
# For PVM fiends only
-$SysMan = ( $INSTALLING ) ? "$InstLibDirGhc/SysMan"
+$SysMan = ( $INSTALLING ) ? "$InstLibExecDirGhc/SysMan"
: "$TopPwd/${CURRENT_DIR}/${GHC_SYSMAN}";
@Unlit_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_UsageSPInf = ''; # Off by default
} # end of setupOptFlags
# Assign defaults to these right away.
\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:
# 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)
$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}
$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",
#
%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" );
-
-# 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', '' );
-
-\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 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 = ();
-@UserLibrary_dir= (); #-L things;...
-@UserLibrary = (); #-l things asked for by the user
+# Cpp symbols defined when we're processing Haskell source.
+
+@HsSourceCppOpts =
+ ( "-D__HASKELL1__=$Haskell1Version"
+ , "-D__GLASGOW_HASKELL__=$ProjectVersionInt"
+ , "-D__HASKELL98__"
+ , "-D__CONCURRENT_HASKELL__"
+ );
+
@SysLibrary_dir = ( ( $INSTALLING ) #-syslib things supplied by the system
? $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"
+ = ( $INSTALLING ) ? "$InstLibExecDirGhc/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;
# 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}
$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 = ();
-
@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
\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; # ""
+$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)-/;
-$ProduceHi = '-hifile=';
-$HiOnStdout = 0;
-$HiDiff_flag = '';
+ if ($HaveNativeCodeGen ne 'YES') && $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;
$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 <file>; "-" for stdout
$Specific_dump_file = ''; # set by -odump <file>; "-" for stdout
$Using_dump_file = 0;
$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;
$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)
# and whatever else
@Cmd_opts = ();
+# cmd line options prefixing the unit we're compiling
+@File_options = ();
+
\end{code}
We inject consistency-checking information into \tr{.hc} files (both
\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 = 31;
-$HsC_minor_version = 0;
-$Cc_major_version = 36;
-$Cc_minor_version = 0;
+$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:
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.
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;
}
+# ..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 <file>} or \tr{-ohi <file>} options...
# (except if linking, of course)
sub setupOptimiseFlags {
+ # this pass-ordering sequence was agreed by Simon and Andr\'e
+ # (WDP 94/07, 94/11).
+
@HsC_minusNoO_flags
- = ( '-fsimplify',
- '\(',
- $Oopt_FB_Support,
-# '-falways-float-lets-from-lets', # no idea why this was here (WDP 95/09)
- '-ffloat-lets-exposing-whnf',
- '-ffloat-primops-ok',
- '-fcase-of-case',
-# '-fdo-lambda-eta-expansion', # too complicated
- '-freuse-con',
-# '-flet-to-case', # no strictness analysis, so...
- $Oopt_PedanticBottoms,
-# $Oopt_MonadEtaExpansion, # no thanks
- '-fsimpl-uf-use-threshold0',
- '-fessential-unfoldings-only',
-# $Oopt_UnfoldingUseThreshold, # no thanks
- $Oopt_MaxSimplifierIterations,
- '\)',
+ = (
+ '-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-case-elim',
+ '-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
- '-fsimpl-uf-use-threshold0',
- '-fessential-unfoldings-only',
- '-fmax-simplifier-iterations1',
- $Oopt_PedanticBottoms,
- '\)',
-
- ($Oopt_DoSpecialise) ? (
- '-fspecialise-overloaded',
- $Oopt_SpecialiseUnboxed,
- $Oopt_DoSpecialise,
- ) : (),
+ '[',
+ '-finline-phase1', # Don't inline rule Ids till specialisation has bitten
- '-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,
- '\)',
-
-#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,
-# '\)',
-# ) : (),
+# APR 99: the stuff in this comment is now
+# handled by -finline-phase1
+#
+# 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. --SLPJ
+#
+# 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',
- # this pass-ordering sequence was agreed by Simon and Andr\'e
- # (WDP 94/07, 94/11).
- '-ffull-laziness',
+ '-fmax-simplifier-iterations2',
+ ']',
- ($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_DoSpecialise) ? ( $Oopt_DoSpecialise, ) : (),
+
+ $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_MaxSimplifierIterations,
+
+ # Still don't inline transformation rule Ids, to give the
+ # rules a good chance to fire
+ '-finline-phase1',
+ ']',
+
+ '-ffull-laziness',
'-ffloat-inwards',
'-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,
- '\)',
+ '[',
+ '-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_MaxSimplifierIterations,
+ # No -finline-phase: allow all Ids to be inlined now
+ ']',
'-ffloat-inwards',
# ( ($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-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_MaxSimplifierIterations,
+ ']',
# '-fstatic-args',
-#LATER: '-fcalc-inlinings2', -- pointless for 2.01
-
# stg2stg passes
- '-fupdate-analysis',
- '-flambda-lift',
+# '-flambda-lift',
$Oopt_FinalStgProfilingMassage,
$Oopt_StgStats,
# SPECIAL FLAGS for -O2
($OptLevel == 2) ? (
+ '-fupdate-analysis', # virtually useless; relegated to -O2
'-fsemi-tagging',
) : (),
);
&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...
}
%* *
%************************************************************************
-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';
- 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++;
- }
+ # Ignore user sccs when auto annotating, but warn when doing so.
+ $PROFignore_scc = '-W' if $PROFauto;
}
#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; }
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; }
} elsif ( $TICKYing eq 't' ) {
$BuildTag = '_t';
- }
+ } elsif ( $UNREGing eq 'u' ) {
+ $BuildTag = '_u';
+ }
\end{code}
After the sanity checks, add flags to the necessary parts of the driver pipeline:
# 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}
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
# (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;
-
# -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;
-
# -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!
# also: -fno-defer-pop is not sufficiently well-behaved without it
} elsif ($TargetPlatform =~ /^mips-/) {
- # we (hope to) know how to *mangle* asm for MIPSen
- unshift(@CcRegd_flags, ('-D__STG_REV_TBLS__'));
- unshift(@CcRegd_flags, ('-DSTACK_CHECK_BY_PAGE_FAULT=1')) if $StkChkByPageFaultOK;
unshift(@CcBoth_flags, ('-static'));
- } elsif ($TargetPlatform =~ /^powerpc-/) {
- # we know how to *mangle* asm for PowerPC
- unshift(@CcRegd_flags, ('-D__STG_REV_TBLS__'));
- 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
-
} 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
local($uscore) = ( ${LeadingUnderscore} eq 'YES' ) ? '_' : '';
unshift(@Ld_flags,
- (($Ld_main) ? (
- '-u', "${uscore}Main_" . $Ld_main . '_closure',
- ) : ()
-# What are these? -- SOF
-# , '-u', "${uscore}STbase_unsafePerformPrimIO_fast1"
-# , '-u', "${uscore}Prelude_Z91Z93_closure" # i.e., []
-# , '-u', "${uscore}Prelude_IZh_static_info"
-# , '-u', "${uscore}Prelude_False_inregs_info"
-# , '-u', "${uscore}Prelude_True_inregs_info"
-# , '-u', "${uscore}Prelude_CZh_static_info"
-# , '-u', "${uscore}DEBUG_REGS"
- ))
- ; # just for fun, now...
+ (($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_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"
+ ));
+ 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
$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';
+ # 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' ) {
}
# 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}
%************************************************************************
@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 (<STDIN>) { print INF $_; }
close(INF) || &tidy_up_and_die(1,"Failed writing to $Tmp_prefix.hs\n");
}
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}
&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;
-
- 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 <<EOSCRIPT1;
-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}
-#
-\$pvm_executable = '$pvm_executable';
-\$pvm_executable_base = '$pvm_executable_base';
-\$SysMan = '$SysMan';
-EOSCRIPT1
-
- print EXEC <<\EOSCRIPT2;
-# first, some magical shortcuts to run "commands" on the binary
-# (which is hidden)
-if ($#ARGV == 1 && $ARGV[0] eq '+RTS' && $ARGV[1] =~ /^--((size|file|strip|rm|nm).*)/ ) {
- local($cmd) = $1;
- system("$cmd $pvm_executable");
- exit(0); # all done
-}
-
-# OK, really run it; process the args first
-$ENV{'PE'} = $pvm_executable_base;
-$debug = '';
-$nprocessors = 2; # the default
-@nonPVM_args = ();
-$in_RTS_args = 0;
-
-# ToDo: handle --RTS
-args: while ($a = shift(@ARGV)) {
- if ( $a eq '+RTS' ) {
- $in_RTS_args = 1;
- } elsif ( $a eq '-RTS' ) {
- $in_RTS_args = 0;
- }
- if ( $a eq '-d' && $in_RTS_args ) {
- $debug = '-';
- } elsif ( $a =~ /^-N(\d+)/ && $in_RTS_args ) {
- $nprocessors = $1;
- } else {
- push(@nonPVM_args, $a);
- }
-}
-
-local($return_val) = 0;
-system("$SysMan $debug $pvm_executable $nprocessors @nonPVM_args");
-$return_val = $?;
-system("mv $ENV{'HOME'}/$pvm_executable_base.???.gr .") if -f "$ENV{'HOME'}/$pvm_executable_base.001.gr";
-exit($return_val);
-EOSCRIPT2
- close(EXEC) || die "Failed closing $executable\n";
- chmod 0755, $executable;
- }
-}
+# Link if appropriate.
+&runLinker() if $Do_lnkr;
# that... that's all, folks!
&tidy_up();
# 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.
? $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';
local($is_hc_file) = 1; #Is the C code .hc or .c? Assume .hc for now
- $lit2pgm_hscpp = $ifile if ($ifile =~ /\.hs$/);
+ # OK, let's strip off some literate junk..
+ if ($do_lit2pgm) {
+ &runLit2pgm($in_lit2pgm, $lit2pgm_hscpp)
+ } else {
+ $lit2pgm_hscpp = $ifile;
+ }
- # OK, let's strip off some literate junk:
- &runLit2pgm($in_lit2pgm, $lit2pgm_hscpp) if ($ifile =~ /\.lhs$/);
#
@File_options = ();
# Scan the top of the de-litted file for {-# OPTIONS #-} pragmas
- &check_for_source_options($lit2pgm_hscpp);
- # options found in the source file take a back seat, i.e., we scan
+ &check_for_source_options($lit2pgm_hscpp,$ifile);
+
+ # 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).
#
if ( $#Input_file >= 0 || $#File_options >= 0) {
- @File_options = (@File_options, @Cmd_opts);
+ #@File_options = (@File_options, @Cmd_opts);
# Now process the command line
&initDriverGlobals();
- &processArgs(@File_options);
+ &processArgs((@File_options,@Cmd_opts));
+ print STDERR "\nEffective command line: " .
+ join(' ',(@File_options,@Cmd_opts)) . "\n" if $Verbose;
}
#
# Having got the effective command line scanned, set up
&setupOptimiseFlags();
&setupMachOpts();
&setupIncPaths();
+ &setupWarningFlags();
&setupHeapStackSize();
#
? $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...
# 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.<suffix>"@.
+
\begin{code}
local($going_interactive) = $HscOut eq '-N=' || $ifile_root eq '_stdin';
# -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
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
}
\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) {
&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;
+ # save a copy of the .s file..
+ &saveIntermediate($ifile_root , "s" , $cc_as) if ($do_as && $Keep_s_file_too);
&runAs($as_out, $ifile_root) if $do_as;
\end{code}
#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);
}
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');
}
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
local($source_unchanged) = 1;
-# Check if the source file is up to date relative to the target; in
-# that case we say "source is unchanged" and let the compiler bail out
-# early if the import usage information allows it.
+ # Check if the source file is up to date relative to the target; in
+ # that case we say "source is unchanged" and let the compiler bail out
+ # early if the import usage information allows it.
($i_dev,$i_ino,$i_mode,$i_nlink,$i_uid,$i_gid,$i_rdev,$i_size,
$i_atime,$i_mtime,$i_ctime,$i_blksize,$i_blocks) = stat($ifile);
- if ( ! -f $ofile_target ) {
-# print STDERR "$Pgm:compile:Output file $ofile_target doesn't exist\n";
+ # The informational messages below are now conditional on -v being set -- SOF
+ 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;
}
($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 ) {
-# print STDERR "$Pgm:compile:Interface file $hifile_target doesn't exist\n";
+ 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;
}
($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) {
-# print STDERR "$Pgm:recompile:Input file $ifile newer than $ofile_target\n";
+ 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) {
push(@HsC_flags, '-fsource-unchanged');
}
-# Run the compiler
+ # Indicate whether we're static or not.
+ # This will only ever
+ push(@HsC_flags, '-static') if $Static;
- &runHsc($ifile_root, $hsc_out, $hsc_hi, $going_interactive);
+ # Run the compiler
-# See if it bailed out early, saying nothing needed doing.
-# We work this out by seeing if it created an output .hi file
+ &runHsc($ifile_root, $hsc_out, $hsc_hi, $hsc_out_c_stub, $hsc_out_h_stub, $going_interactive);
- if ( ! -f $hsc_hi ) {
+ # See if it bailed out early, saying nothing needed doing.
+ # We work this out by seeing if it created an output .hi file
+
+ if ( ! -f $hsc_hi && $ProduceHi !~ /-nohifile=/ ) {
# Doesn't exist, so we bailed out early.
# Tell the C compiler and assembler not to run
$do_cc = 0; $do_as = 0;
# out early, we still need to touch the interface file of B. The reason
# for this is that B may export A's interface.
#
- &run_something("touch $ofile_target $hifile_target",
- "Touch $ofile_target $hifile_target, to propagate dependencies");
+ &run_something("touch $ofile_target",
+ "Touch $ofile_target, to propagate dependencies") if $HscOut ne '-N=';
+ &run_something("touch $hifile_target",
+ "Touch $hifile_target, to propagate dependencies") if $ProduceHi =~ /-nohifile=/ ;
} else {
# Interface-handling is important enough to live off by itself
- require('ghc-iface.prl')
- || &tidy_up_and_die(1,"$Pgm: panic: can't load ghc-iface.prl!\n");
-
- &postprocessHiFile($hsc_hi, $hifile_target, $going_interactive);
-
- # save a copy of the .hc file, even if we are carrying on...
- if ($HscOut eq '-C=' && $do_cc && $Keep_hc_file_too) {
- local($to_do) = "$Rm $ifile_root.hc; $Cp $hsc_out $ifile_root.hc";
- &run_something($to_do, 'Saving copy of .hc file');
- }
-
- # save a copy of the .s file, even if we are carrying on...
- if ($HscOut eq '-S=' && $do_as && $Keep_s_file_too) {
- local($to_do) = "$Rm $ifile_root.s; $Cp $hsc_out $ifile_root.s";
- &run_something($to_do, 'Saving copy of .s file');
+ if ( $ProduceHi !~ /-nohifile=/ ) { # If we've produced one, process it.
+ require('ghc-iface.prl') || &tidy_up_and_die(1,"$Pgm: panic: can't load ghc-iface.prl!\n");
+ &postprocessHiFile($hsc_hi, $hifile_target, $going_interactive);
}
-
# if we're going to split up object files,
# we inject split markers into the .hc file now
if ( $HscOut eq '-C=' && $SplitObjFiles ) {
&inject_split_markers ( $hsc_out );
}
+
+ # save a copy of the .hc file, even if we are carrying on...
+ if ($HscOut eq '-C=' && $do_cc && $Keep_hc_file_too) {
+ &saveIntermediate($ifile_root , "hc" , $hsc_out);
+ }
+
}
}
\end{code}
\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=$HiMapFile");
# 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:
- $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";
- @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 ) {
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");
}
}
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
Use \tr{@Import_dir} and \tr{@SysImport_dir} to make a tmp file
of (module-name, pathname) pairs, one per line, separated by a space.
\begin{code}
-#%HiMap = ();
$HiMapDone = 0;
-$HiMapFile = '';
$HiIncludeString = (); # dir1:dir2:dir3, to pass to GHC
sub makeHiMap {
local($mod, $path, $d, $e);
# reset the global variables:
- #%HiMap = ();
$HiMapDone = 0;
- $HiMapFile = '';
$HiIncludeString = (); # dir1:dir2:dir3, to pass to GHC
foreach $d ( @Import_dir ) {
- if ($HiIncludeString) { $HiIncludeString = "$HiIncludeString:$d";
- } else { $HiIncludeString = $d; }
+ if ($HiIncludeString) {
+ $HiIncludeString = "$HiIncludeString:${d}%.${HiSuffix}";
+ } else {
+ $HiIncludeString = "$d%.${HiSuffix}";
+ }
-# The compiler does the searching now
-#
-# opendir(DIR, $d) || &tidy_up_and_die(1,"$Pgm: error when reading directory: $d\n");
-# local(@entry) = readdir(DIR);
-# foreach $e ( @entry ) {
-# next unless $e =~ /\b([A-Z][A-Za-z0-9_]*)\.${HiSuffix_prelude}$/o;
-# $mod = $1;
-# $path = "$d/$e";
-# $path =~ s,^\./,,;
-#
-# if ( ! defined($HiMap{$mod}) ) {
-# $HiMap{$mod} = $path;
-# } else {
-# &already_mapped_err($mod, $HiMap{$mod}, $path);
-# }
-# }
-# closedir(DIR); # || &tidy_up_and_die(1,"$Pgm: error when closing directory: $d\n");
}
foreach $d ( @SysImport_dir ) {
- if ($HiIncludeString) { $HiIncludeString = "$HiIncludeString:$d";
- } else { $HiIncludeString = $d; }
-
-# opendir(DIR, $d) || &tidy_up_and_die(1,"$Pgm: error when reading directory: $d\n");
-# local(@entry) = readdir(DIR);
-# foreach $e ( @entry ) {
-# next unless $e =~ /([A-Z][A-Za-z0-9_]*)\.$HiSuffix$/o;
-# next if $NoImplicitPrelude && $e =~ /Prelude\.$HiSuffix$/o;
-#
-# $mod = $1;
-# $path = "$d/$e";
-# $path =~ s,^\./,,;
-#
-# if ( ! defined($HiMap{$mod}) ) {
-# $HiMap{$mod} = $path;
-# } elsif ( $mod ne 'Main' ) { # saves useless warnings...
-# &already_mapped_err($mod, $HiMap{$mod}, $path);
-# }
-# }
-# closedir(DIR); # || &tidy_up_and_die(1,"$Pgm: error when closing directory: $d\n");
+ if ($HiIncludeString) {
+ $HiIncludeString = "$HiIncludeString:${d}%.${HiSuffix_prelude}";
+ } else {
+ $HiIncludeString = "${d}%.${HiSuffix_prelude}";
+ }
}
+ $HiMapDone = 1;
+}
+
+\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 $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 <<EOSCRIPT1;
+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}
#
-# Not currently used:
-#
-# $HiMapFile = "$Tmp_prefix.himap";
-# unlink($HiMapFile);
-# open(HIMAP, "> $HiMapFile") || &tidy_up_and_die(1,"$Pgm: can't open $HiMapFile\n");
-# foreach $d (keys %HiMap) {
-# print HIMAP $d, ' ', $HiMap{$d}, "\n";
-# }
-# close(HIMAP) || &tidy_up_and_die(1,"$Pgm: error when closing $HiMapFile\n");
+\$pvm_executable = '$pvm_executable';
+\$pvm_executable_base = '$pvm_executable_base';
+\$SysMan = '$SysMan';
+EOSCRIPT1
- $HiMapDone = 1;
+ print EXEC <<\EOSCRIPT2;
+# first, some magical shortcuts to run "commands" on the binary
+# (which is hidden)
+if ($#ARGV == 1 && $ARGV[0] eq '+RTS' && $ARGV[1] =~ /^--((size|file|strip|rm|nm).*)/ ) {
+ local($cmd) = $1;
+ system("$cmd $pvm_executable");
+ exit(0); # all done
+}
+
+# OK, really run it; process the args first
+$ENV{'PE'} = $pvm_executable_base;
+$debug = '';
+$nprocessors = 2; # the default
+@nonPVM_args = ();
+$in_RTS_args = 0;
+
+# ToDo: handle --RTS
+args: while ($a = shift(@ARGV)) {
+ if ( $a eq '+RTS' ) {
+ $in_RTS_args = 1;
+ } elsif ( $a eq '-RTS' ) {
+ $in_RTS_args = 0;
+ }
+ if ( $a eq '-d' && $in_RTS_args ) {
+ $debug = '-';
+ } elsif ( $a =~ /^-N(\d+)/ && $in_RTS_args ) {
+ $nprocessors = $1;
+ } else {
+ push(@nonPVM_args, $a);
+ }
+}
+
+local($return_val) = 0;
+system("$SysMan $debug $pvm_executable $nprocessors @nonPVM_args");
+$return_val = $?;
+system("mv $ENV{'HOME'}/$pvm_executable_base.???.gr .") if -f "$ENV{'HOME'}/$pvm_executable_base.001.gr";
+exit($return_val);
+EOSCRIPT2
+ close(EXEC) || die "Failed closing $executable\n";
+ chmod 0755, $executable;
+ }
}
-sub already_mapped_err {
- local($mod, $mapped_to, $path) = @_;
+sub createWin32DLL()
+{
+ 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;
+
+ &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");
+ }
- # OK, it isn't really an error if $mapped_to and $path turn
- # out to be the same thing.
- ($m_dev,$m_ino,$m_mode,$m_nlink,$m_uid,$m_gid,$m_rdev,$m_size,
- $m_atime,$m_mtime,$m_ctime,$m_blksize,$m_blocks) = stat($mapped_to);
- ($p_dev,$p_ino,$p_mode,$p_nlink,$p_uid,$p_gid,$p_rdev,$p_size,
- $p_atime,$p_mtime,$p_ctime,$p_blksize,$p_blocks) = stat($path);
+ 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');
+}
- return if $m_ino == $p_ino; # same inode number
+sub prepareWin32DllLink ()
+{
+ local($linking_main) = @_;
- print STDERR "$Pgm: module $mod already mapped to $mapped_to";
- print STDERR ";\n\tignoring: $path\n";
+ #
+ # 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.o"
+ : "$TopPwd/$CURRENT_DIR/$GHC_RUNTIME_DIR/Main.o") if $linking_main;
+ push(@Link_file, ( $INSTALLING ) ? "$InstLibDirGhc/PrelMain.o"
+ : "$TopPwd/$CURRENT_DIR/$GHC_LIB_DIR/PrelMain.o") if $linking_main;
+ }
+ push(@Ld_flags, "-mno-cygwin");
+ }
}
\end{code}
+
%************************************************************************
%* *
\section[Driver-misc-utils]{Miscellaneous utilities}
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 =~ /^(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";
open(TMP, "> $cc_help") || &tidy_up_and_die(1,"$Pgm: failed to open `$cc_help' (to write)\n");
if ( $is_hc_file ) {
print TMP <<EOINCL;
-#ifdef __STG_GCC_REGS__
-# if ! (defined(MAIN_REG_MAP) || defined(MARK_REG_MAP) || defined(SCAN_REG_MAP) || defined(SCAV_REG_MAP) || defined(FLUSH_REG_MAP))
-# define MAIN_REG_MAP
-# endif
-#endif
-#include "stgdefs.h"
+#include "Stg.h"
EOINCL
# user may have asked for #includes to be injected...
print TMP @CcInjects if $#CcInjects >= 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}
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')
|| &tidy_up_and_die(1,"$Pgm: panic: can't load ghc-asm-hppa.prl!\n");
&mini_mangle_asm_hppa($cc_as_o, $cc_as);
- } elsif ($TargetPlatform =~ /^i386/) {
- # extremely-minor OFFENSIVE mangling of non-threaded just one file
+ } elsif ($TargetPlatform =~ /^powerpc|^rs6000/) {
+ # minor mangling of non-threaded files for powerpcs and rs6000s
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);
+ || &tidy_up_and_die(1,"$Pgm: panic: can't load ghc-asm-powerpc.prl!\n");
+ &mini_mangle_asm_powerpc($cc_as_o, $cc_as);
}
# save a copy of the .s file, even if we are carrying on...
- if ($do_as && $Keep_s_file_too) {
- local($to_do) = "$Rm $ifile_root.s; $Cp $cc_as $ifile_root.s";
- &run_something($to_do, 'Saving copy of .s file');
- }
+ #if ($do_as && $Keep_s_file_too) {
+ # &saveIntermediate($ifile_root , "s" , $cc_as);
+ #}
}
\end{code}
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...
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');
}
}
local($return_val) = 0;
- system("$Time $str_to_do");
- $return_val = $?;
+
+ if ( length($str_to_do) > 4000) {
+ # 4000 - on the random side, just like the *real* ARG_MAX
+ # for some shells.
+
+ # With some shells, command lines of this length may
+ # very well cause trouble. To safeguard against this, we squirrel the
+ # command into a file and exec that.
+ local ($sh) = $ENV{'REAL_SHELL'};
+ print STDERR "Backup plan A: saving cmd line in ${Tmp_prefix}.sh and executing that with $sh\n" if $Verbose;
+ open (TEMP, "> ${Tmp_prefix}.sh") ||
+ &tidy_up_and_die(1,"$Pgm: failed to open `$Tmp_prefix.sh'\n");
+ print TEMP "$Time $str_to_do\n";
+ close (TEMP) ||
+ &tidy_up_and_die(1,"$Pgm: failed closing `$Tmp_prefix.sh'\n");
+ system("$sh $Tmp_prefix.sh");
+ $return_val = $?;
+
+ unlink "${Tmp_prefix}.sh";
+ } else {
+ system("$Time $str_to_do");
+ $return_val = $?;
+ }
if ( $PostprocessCcOutput ) { # hack, continued
open(CCOUT, "< $Tmp_prefix.ccout")
|| &tidy_up_and_die(1,"$Pgm: failed to open `$Tmp_prefix.ccout'\n");
while ( <CCOUT> ) {
- 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/;
if ($Using_dump_file) {
print STDERR "Compilation Errors dumped in $Specific_dump_file\n";
}
-
&tidy_up_and_die($return_val, '');
}
$Using_dump_file = 0;
%************************************************************************
%* *
-\subsection[Driver-ghctiming]{Emit nofibbish GHC timings}
+\subsection[Driver-ghc-timing]{Emit nofibbish 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 (<STATS>) {
- $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+([0-9]+)\s+Mb total memory/ ) {
+ $TotMem = $1;
+ }
- if ( /^\s*INIT\s+time\s*(\d+\.\d\d)s\s*\(\s*(\d+\.\d\d)s elapsed\)/ ) {
+ # 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;
}
}
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
# 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
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);
}
\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
+ ],
+ 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..
+
+ 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
\begin{code}
sub check_for_source_options {
- local($file) = @_;
+ local($file,$ifile) = @_;
+ local($comment_start,$comment_end);
+
+ if ($ifile =~ /\.hc$/ ||
+ $ifile =~ /_hc$/ ||
+ $ifile =~ /\.s$/ ||
+ $ifile =~ /_s$/ ) { # `Real' C intermediate
+ $comment_start = "/\\*";
+ $comment_end = "\\*/";
+ } else { # Assume it is a file containing Haskell source
+ $comment_start = "{-#";
+ $comment_end = "#-}";
+ }
open(FILE,$file) || return(1); # No big loss
-
+
while (<FILE>) {
- if ( /^{-# OPTIONS (.*)#-}/ ) {
+ 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;
push(@File_options, @entries);
}
elsif ( /^$/ ) { # ignore empty lines
;
}
+ elsif ( /^#line.+$/ ) { # ignore comment lines (unused..ToDo: rm )
+ ;
+ }
+ elsif ( /^{-# LINE.+$/ ) { # ignore line pragmas
+ ;
+ }
else { # stop looking, something non-empty / not
- # {-# OPTIONS .. #-} encountered.
- break;
+ # ${comment_start} OPTIONS .. ${comment_end} encountered.
+ close(FILE);return(0);
}
}
close(FILE);
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, $_);
\end{code}
+When saving an intermediate file (.hc or .s) away, we
+have to prefix any OPTIONS found in the original source file.
+
+\begin{code}
+sub saveIntermediate {
+ local ($final,$suffix,$tmp)= @_ ;
+ local ($to_do);
+
+ # $final -- root of where to park ${final}.${suffix}
+ # $tmp -- temporary file where hsc put the intermediate file.
+
+ # Delete the old file
+ $to_do = "$Rm ${final}.${suffix}"; &run_something($to_do, "Removing old .${suffix} file");
+
+ if ( $#File_options >= 0 ) { # OPTIONS found in Haskell source unit
+ # Add OPTION comment to the top of the generated .${suffix} file
+ open(TEMP, "> ${final}.${suffix}") || &tidy_up_and_die(1,"Can't open ${final}.${suffix}\n");
+ print TEMP "/* OPTIONS " . join(' ',@File_options) . " */\n";
+ close(TEMP);
+ print STDERR "Prepending OPTIONS: " . join(' ',@File_options) . " to ${final}.${suffix}\n" if $Verbose;
+ }
+ $to_do = "$Cat $tmp >> ${final}.${suffix}";
+ &run_something($to_do, "Saving copy of .${suffix} file");
+
+}
+
+\end{code}
+
+
Command-line processor
\begin{code}
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:
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');
# 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
# 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$$";
$Status++;
}
}
+ $ProduceHi='-hifile=';
next arg; };
# The suffix to use when looking for interface files
$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;
/^-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
: '-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" --------------------------------------------
/^-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; };
#=======================================================================
/^-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; };
+ /^-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; };
/^-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; };
- /^-user-prelude-force/ && do { # ignore if not -user-prelude
- next arg; };
-
- /^-split-objs/ && do {
- if ( $TargetPlatform !~ /^(alpha|hppa1\.1|i386|m68k|mips|powerpc|sparc)-/ ) {
+ /^-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";
} else {
}
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; };
/^-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; };
+ # --------------- Renamer -------------
- /^-fno-enable-tech$/
- && do { $Oopt_FB_Support = '';
- next arg; };
- /^-fno-snapback-to-append$/
- && do { $Oopt_FoldrBuildInline .= ' -fdo-not-fold-back-append ';
- next arg; };
+ /^-fno-prune-tydecls$/ && do { push(@HsC_flags, $_); next arg; };
+ /^-fno-prune-instdecls$/ && do { push(@HsC_flags, $_); next arg; };
# ---------------
/^-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);
/^-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. ------
- /^-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,
# -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; };
/^-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; };
}
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]$/) {
#---------- 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...