%
-% (c) The GRASP/AQUA Project, Glasgow University, 1992-1995
+% (c) The GRASP/AQUA Project, Glasgow University, 1992-1996
%
% *** MSUB does some substitutions here ***
% *** grep for $( ***
- hscpp: run code through the C pre-processor (if -cpp flag given)
- hsc: run the Haskell compiler proper
- gcc: run the C compiler (if compiling via C)
- - as: run the Unix assembler
- - ld: run the Unix linker
+ - as: run the assembler
+ - ld: run the linker
For each input file, the phase to START with is determined by the
file's suffix:
- - .lhs literate Haskell: lit2pgm
- - .hs illiterate Haskell: hsp
+ - .lhs literate Haskell: unlit
+ - .hs illiterate Haskell: hsc
- .hc C from the Haskell compiler: gcc
- .c C not from the Haskell compiler: gcc
- .s assembly language: as
Other commonly-used options are:
- -O An `optimising' package of options, to produce faster code
+ -O An `optimising' package of compiler flags, for faster code
-prof Compile for cost-centre profiling
(add -auto for automagic cost-centres on top-level functions)
$TopPwd = '$(TOP_PWD)';
$InstLibDirGhc = '$(INSTLIBDIR_GHC)';
$InstDataDirGhc = '$(INSTDATADIR_GHC)';
+# $InstSysLibDir = '$(INSTLIBDIR_HSLIBS)'; ToDo ToDo
+ $InstSysLibDir = '$(TOP_PWD)/hslibs';
} else {
$TopPwd = $ENV{'GLASGOW_HASKELL_ROOT'};
- if ( '$(INSTLIBDIR_GHC)' =~ /^\/(local\/fp|usr\/local)(\/.*)/ ) {
- $InstLibDirGhc = $ENV{'GLASGOW_HASKELL_ROOT'} . $2;
+ if ('$(INSTLIBDIR_GHC)' =~ /.*(\/lib\/ghc\/\d\.\d\d\/[^-]-[^-]-[^-]\/.*)/) {
+ $InstLibDirGhc = $ENV{'GLASGOW_HASKELL_ROOT'} . $1;
} else {
print STDERR "GLASGOW_HASKELL_ROOT environment variable is set;\nBut can't untangle $(INSTLIBDIR_GHC).\n(Installation error)\n";
exit(1);
}
- if ( '$(INSTDATADIR_GHC)' =~ /\/(local\/fp|usr\/local)(\/.*)/ ) {
+ if ('$(INSTDATADIR_GHC)' =~ /.*(\/lib\/ghc\/\d\.\d\d\/.*)/) {
$InstDataDirGhc = $ENV{'GLASGOW_HASKELL_ROOT'} . $2;
} else {
print STDERR "GLASGOW_HASKELL_ROOT environment variable is set;\nBut can't untangle $(INSTDATADIR_GHC).\n(Installation error)\n";
$Status = 0; # just used for exit() status
$Verbose = '';
-$CoreLint = '';
-$Time = ''; # ToDo: mkworld-ize the timing command
# set up signal handler
sub quit_upon_signal { &tidy_up_and_die(1, ''); }
# where to get "require"d .prl files at runtime (poor man's dynamic loading)
# (use LIB, not DATA, because we can't be sure of arch-independence)
-@INC = ( ( $(INSTALLING) ) ? "$InstLibDirGhc"
+@INC = ( ( $(INSTALLING) ) ? $InstLibDirGhc
: "$TopPwd/$(CURRENT_DIR)" );
if ( $ENV{'TMPDIR'} ) { # where to make tmp file names
: "$TopPwd/$(CURRENT_DIR)/$(GHC_UNLIT)";
@Unlit_flags = ();
-$Cat = "cat";
+$Cp = '$(CP)';
+$Rm = '$(RM)';
+$Diff = '$(CONTEXT_DIFF)';
+$Cat = 'cat';
+$Cmp = 'cmp';
+$Time = '';
$HsCpp = # but this is re-set to "cat" (after options) if -cpp not seen
( $(INSTALLING) ) ? "$InstLibDirGhc/hscpp"
: "$TopPwd/$(CURRENT_DIR)/$(GHC_HSCPP)";
@HsCpp_flags = ();
-
-$HsP = ( $(INSTALLING) ) ? "$InstLibDirGhc/hsp"
- : "$TopPwd/$(CURRENT_DIR)/$(GHC_HSP)";
-@HsP_flags = ();
+$genSPECS_flag = ''; # See ../utils/hscpp/hscpp.prl
$HsC = ( $(INSTALLING) ) ? "$InstLibDirGhc/hsc"
: "$TopPwd/$(CURRENT_DIR)/$(GHC_HSC)";
# terrible things to cache behavior.
$Specific_heap_size = 6 * 1000 * 1000;
$Specific_stk_size = 1000 * 1000;
-$Scale_sizes_by = 1.0;
-$RTS_style = $(GHC_RTS_STYLE);
-@HsC_rts_flags = ();
+$Scale_sizes_by = 1.0;
+@HsC_rts_flags = ();
+@HsP_flags = (); # these are the flags destined solely for
+ # the flex/yacc parser
@HsC_flags = ();
@HsC_antiflags = ();
\end{code}
expressed with a \tr{-O} (or \tr{-O2}) flag, or by its absence.
\begin{code}
-$OptLevel = 0; # no -O == 0; -O == 1; -O2 == 2; -Ofile == 3
-$MinusO2ForC = 0; # set to 1 if -O2 should be given to C compiler
-$StolenX86Regs = 5; # **HACK*** of the very worst sort
-$SpX86Mangling = 1; # **EXTREME HACK*** of an even worse sort
+$OptLevel = 0; # no -O == 0; -O == 1; -O2 == 2; -Ofile == 3
+$MinusO2ForC = 0; # set to 1 if -O2 should be given to C compiler
+$StolenX86Regs = 4; # **HACK*** of the very worst sort
+$CoreLint = '';
\end{code}
These variables represent parts of the -O/-O2/etc ``templates,''
$Oopt_MaxSimplifierIterations = '-fmax-simplifier-iterations4';
$Oopt_PedanticBottoms = '-fpedantic-bottoms'; # ON by default
$Oopt_MonadEtaExpansion = '';
-#OLD:$Oopt_LambdaLift = '';
-$Oopt_AddAutoSccs = '';
$Oopt_FinalStgProfilingMassage = '';
+$Oopt_StgStats = '';
$Oopt_SpecialiseUnboxed = '';
-$Oopt_FoldrBuild = 1; # On by default!
-$Oopt_FB_Support = '-fdo-new-occur-anal -fdo-arity-expand';
+$Oopt_DoSpecialise = ''; # ToDo:LATER: '-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';
\end{code}
Things to do with C compilers/etc:
\begin{code}
-$CcUnregd = '$(GHC_DEBUG_HILEV_ASM)'; # our high-level assembler (non-optimising)
-$CcRegd = '$(GHC_OPT_HILEV_ASM)'; # our high-level assembler (optimising)
-$GccAvailable = $(GHC_GCC_IS_AVAILABLE); # whether GCC avail or not for optimising
-
+$CcRegd = 'gcc';
@CcBoth_flags = ('-S'); # flags for *any* C compilation
@CcInjects = ();
-# non-registerizing flags: those for all files, those only for .c files; those only for .hc files
-@CcUnregd_flags = ( $GccAvailable ) ? ('-ansi', '-pedantic') : ();
-@CcUnregd_flags_c = ();
-@CcUnregd_flags_hc= ();
-
-# ditto; but for registerizing (we must have GCC for this)
+# GCC flags: those for all files, those only for .c files; those only for .hc files
@CcRegd_flags = ('-ansi', '-D__STG_GCC_REGS__', '-D__STG_TAILJUMPS__');
@CcRegd_flags_c = ();
@CcRegd_flags_hc = ();
-$As = ''; # assembler is normally the same pgm as used for C compilation
+$As = ''; # "assembler" is normally GCC
@As_flags = ();
-$Lnkr = ''; # linker is normally the same pgm as used for C compilation
+$Lnkr = ''; # "linker" is normally GCC
+@Ld_flags = ();
# 'nm' is used for consistency checking (ToDo: mk-world-ify)
# ToDo: check the OS or something ("alpha" is surely not the crucial question)
'_l', '$(GHC_BUILD_FLAG_l)',
'_m', '$(GHC_BUILD_FLAG_m)',
'_n', '$(GHC_BUILD_FLAG_n)',
- '_o', '$(GHC_BUILD_FLAG_o)' );
+ '_o', '$(GHC_BUILD_FLAG_o)',
+ '_A', '$(GHC_BUILD_FLAG_A)',
+ '_B', '$(GHC_BUILD_FLAG_B)' );
%BuildDescr = ('', 'normal sequential',
'_p', 'profiling',
'_t', 'ticky-ticky profiling',
- '_t', 'unregisterized (using portable C only)',
+#OLD: '_u', 'unregisterized (using portable C only)',
'_mc', 'concurrent',
'_mr', 'profiled concurrent',
'_mt', 'ticky concurrent',
'_l', 'user way l',
'_m', 'user way m',
'_n', 'user way n',
- '_o', 'user way o' );
+ '_o', 'user way o',
+ '_A', 'user way A',
+ '_B', 'user way B' );
# these are options that are "fed back" through the option processing loop
%UserSetupOpts = ('_a', '$(GHC_BUILD_OPTS_a)',
'_m', '$(GHC_BUILD_OPTS_m)',
'_n', '$(GHC_BUILD_OPTS_n)',
'_o', '$(GHC_BUILD_OPTS_o)',
+ '_A', '$(GHC_BUILD_OPTS_A)',
+ '_B', '$(GHC_BUILD_OPTS_B)',
# the GC ones don't have any "fed back" options
'_2s', '',
# profiled sequential
'_p', 'push(@HsC_flags, \'-fscc-profiling\');
- push(@CcBoth_flags, \'-DUSE_COST_CENTRES\');',
+ push(@CcBoth_flags, \'-DPROFILING\');',
+
+ #and maybe ...
+ #push(@CcBoth_flags, '-DPROFILING_DETAIL_COUNTS');
# ticky-ticky sequential
- '_t', 'push(@HsC_flags, \'-fstg-reduction-counts\');
- push(@CcBoth_flags, \'-DDO_REDN_COUNTING\');',
+ '_t', 'push(@HsC_flags, \'-fticky-ticky\');
+ push(@CcBoth_flags, \'-DTICKY_TICKY\');',
- # unregisterized (ToDo????)
- '_u', '',
+#OLD: # unregisterized (ToDo????)
+# '_u', '',
# concurrent
'_mc', '$StkChkByPageFaultOK = 0;
'_mr', '$StkChkByPageFaultOK = 0;
push(@HsC_flags, \'-fconcurrent\', \'-fscc-profiling\');
push(@HsCpp_flags,\'-D__CONCURRENT_HASKELL__\', \'-DCONCURRENT\');
- push(@Cpp_define, \'-D__CONCURRENT_HASKELL__\', \'-DCONCURRENT\', \'-DUSE_COST_CENTRES\');',
+ push(@Cpp_define, \'-D__CONCURRENT_HASKELL__\', \'-DCONCURRENT\', \'-DPROFILING\');',
# ticky-ticky concurrent
'_mt', '$StkChkByPageFaultOK = 0;
- push(@HsC_flags, \'-fconcurrent\', \'-fstg-reduction-counts\');
+ push(@HsC_flags, \'-fconcurrent\', \'-fticky-ticky\');
push(@HsCpp_flags,\'-D__CONCURRENT_HASKELL__\', \'-DCONCURRENT\');
- push(@Cpp_define, \'-D__CONCURRENT_HASKELL__\', \'-DCONCURRENT\', \'-DDO_REDN_COUNTING\');',
+ 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\', \'-DGUM\');',
+ push(@Cpp_define, \'-D__CONCURRENT_HASKELL__\', \'-DCONCURRENT\', \'-DPAR\');',
# GranSim
'_mg', '$StkChkByPageFaultOK = 0;
- push(@HsC_flags, \'-fconcurrent\');
-#???????????? push(@HsCpp_flags,\'-D__PARALLEL_HASKELL__\', \'-DPAR\');
+ push(@HsC_flags, \'-fconcurrent\', \'-fgransim\');
+ push(@HsCpp_flags,\'-D__GRANSIM__\', \'-DGRAN\');
push(@Cpp_define, \'-D__CONCURRENT_HASKELL__\', \'-DCONCURRENT\', \'-DGRAN\');',
'_2s', 'push (@CcBoth_flags, \'-DGC2s\');',
'_l', '',
'_m', '',
'_n', '',
- '_o', '' );
+ '_o', '',
+ '_A', '',
+ '_B', '' );
\end{code}
Import/include directories (\tr{-I} options) are sufficiently weird to
@SysImport_dir = ( $(INSTALLING) )
? ( "$InstDataDirGhc/imports" )
: ( "$TopPwd/$(CURRENT_DIR)/$(GHC_LIBSRC)/prelude"
- );
+ , "$TopPwd/$(CURRENT_DIR)/$(GHC_LIBSRC)/required"
+ , "$TopPwd/$(CURRENT_DIR)/$(GHC_LIBSRC)/concurrent" );
-$ghc_version_info = $(PROJECTVERSION) * 100;
-$haskell1_version = 2; # i.e., Haskell 1.2
-@Cpp_define = ();
+$GhcVersionInfo = int ($(PROJECTVERSION) * 100);
+$Haskell1Version = 3; # i.e., Haskell 1.3
+@Cpp_define = ();
@UserLibrary_dir= (); #-L things;...
@UserLibrary = (); #-l things asked for by the user
@SysLibrary_dir = ( ( $(INSTALLING) ) #-syslib things supplied by the system
- ? "$InstLibDirGhc"
- : ("$TopPwd/$(CURRENT_DIR)/$(GHC_RUNTIMESRC)",
- "$TopPwd/$(CURRENT_DIR)/$(GHC_RUNTIMESRC)/gmp",
- "$TopPwd/$(CURRENT_DIR)/$(GHC_LIBSRC)")
+ ? $InstLibDirGhc
+ : ( "$TopPwd/$(CURRENT_DIR)/$(GHC_RUNTIMESRC)"
+ , "$TopPwd/$(CURRENT_DIR)/$(GHC_RUNTIMESRC)/gmp"
+ , "$TopPwd/$(CURRENT_DIR)/$(GHC_LIBSRC)"
+ , "$TopPwd/$(CURRENT_DIR)/$(GHC_LIBSRC)/cbits"
+ )
);
-@SysLibrary = ( '-lHS' ); # basic I/O and prelude stuff
+@SysLibrary = (); # will be built up as we go along
$TopClosureFile # defaults to 1.2 one; will be mangled later
= ( $(INSTALLING) ) ? "$InstLibDirGhc/TopClosureXXXX.o"
Here are the initial defaults applied to all files:
\begin{code}
-$Do_lit2pgm = 1;
-$Do_hscpp = 1; # but we run 'cat' by default (see after arg check)
$Cpp_flag_set = 0; # (hack)
$Only_preprocess_C = 0; # pretty hackish
-$ProduceHi = 1; # but beware magical value "2"! (hack)
$PostprocessCcOutput = 0;
-$HiDiff_flag= 0;
# native code-gen or via C?
$HaveNativeCodeGen = $(GHC_WITH_NATIVE_CODEGEN);
-$ProduceS = '';
-if ($HaveNativeCodeGen) {
- if ($TargetPlatform =~ /^(alpha|sparc)-/) {
- $ProduceS = $TargetPlatform;
- }
-}
-$ProduceC = ($ProduceS) ? 0 : 1;
+$HscOut = '-C='; # '-C=' ==> .hc output; '-S=' ==> .s output; '-N=' ==> neither
+$HscOut = '-S='
+ if $HaveNativeCodeGen && $TargetPlatform =~ /^(alpha|sparc)-/; #ToDo: add |i386 !
+$ProduceHi = '-hifile=';
+$HiOnStdout = 0;
+$HiDiff_flag = '';
$CollectingGCstats = 0;
$CollectGhcTimings = 0;
-$RegisteriseC = ''; # set to 'o', if using optimised C code (only if avail)
- # or if generating equiv asm code
$DEBUGging = ''; # -DDEBUG and all that it entails (um... not really)
$PROFing = ''; # set to p or e if profiling
-$PROFaging = ''; # set to a if profiling with age -- only for cc consistency
$PROFgroup = ''; # set to group if an explicit -Ggroup specified
$PROFauto = ''; # set to relevant hsc flag if -auto or -auto-all
$PROFcaf = ''; # set to relevant hsc flag if -caf-all
-#UNUSED:$PROFdict = ''; # set to relevant hsc flag if -dict-all
$PROFignore_scc = ''; # set to relevant parser flag if explicit sccs ignored
+$UNPROFscc_auto = ''; # set to relevant hsc flag if forcing auto sccs without profiling
$TICKYing = ''; # set to t if compiling for ticky-ticky profiling
-$PARing = ''; # set to p if compiling for PAR (ie GUM)
+$PARing = ''; # set to p if compiling for PAR
$CONCURing = ''; # set to c if compiling for CONCURRENT
$GRANing = ''; # set to g if compiling for GRAN
$StkChkByPageFaultOK = 1; # may be set to 0 (false) for some builds
$Specific_hi_file = ''; # set by -ohi <file>; "-" for stdout
$Specific_dump_file = ''; # set by -odump <file>; "-" for stdout
$Using_dump_file = 0;
-$Osuffix = '.o';
-$HiSuffix = '.hi';
-$Do_hsp = 2; # 1 for "old" parser; 2 for "new" parser (in hsc)
-$Do_hsc = 1;
+$Isuffix = '';
+$Osuffix = ''; # default: use the normal suffix for that kind of output
+$HiSuffix = 'hi';
+$SysHiSuffix= 'hi';
+$Do_recomp_chkr = 0; # don't use the recompilatio checker unless asked
$Do_cc = -1; # a MAGIC indeterminate value; will be set to 1 or 0.
$Do_as = 1;
$Do_lnkr = 1;
$Keep_hc_file_too = 0;
$Keep_s_file_too = 0;
-$CompilingPrelude = 0;
+$UseGhcInternals = 0; # if 1, may use GHC* modules
$SplitObjFiles = 0;
$NoOfSplitFiles = 0;
$Dump_parser_output = 0;
$Dump_raw_asm = 0;
-$Dump_asm_insn_counts = 0;
-$Dump_asm_globals_info = 0;
$Dump_asm_splitting_info = 0;
+$NoImplicitPrelude = 0;
# and the list of files
@Input_file = ();
# major & minor version numbers; major numbers must always agree;
# minor disagreements yield a warning.
-$HsC_major_version = 29;
+$HsC_major_version = 30;
$HsC_minor_version = 0;
-$Cc_major_version = 33;
+$Cc_major_version = 35;
$Cc_minor_version = 0;
# options: these must always agree
$HsC_consist_options = ''; # we record, in this order:
# Build tag; debugging?
$Cc_consist_options = ''; # we record, in this order:
- # Build tag; debugging? registerised?
+ # Build tag; debugging?
\end{code}
%************************************************************************
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";
+}
+
# can't use getopt(s); what we want is too complicated
arg: while($_ = $ARGV[0]) {
shift(@ARGV);
/^-v$/ && do { $Verbose = '-v'; $Time = 'time'; next arg; };
#---------- what phases are to be run ----------------------------------
+ /^-recomp/ && do { $Do_recomp_chkr = 1; next arg; };
+
/^-cpp$/ && do { $Cpp_flag_set = 1; next arg; };
# change the global default:
# we won't run cat; we'll run the real thing
- /^-C$/ && do { $Do_cc = 0; $Do_as = 0; $Do_lnkr = 0;
- $ProduceC = 1; $ProduceS = '';
+ /^-C$/ && do { $Do_cc = 0; $Do_as = 0; $Do_lnkr = 0; $HscOut = '-C=';
next arg; };
# stop after generating C
- /^-noC$/ && do { $ProduceC = 0; $ProduceS = ''; $ProduceHi = 0;
+ /^-noC$/ && do { $HscOut = '-N='; $ProduceHi = '-nohifile=';
$Do_cc = 0; $Do_as = 0; $Do_lnkr = 0;
next arg; };
# leave out actual C generation (debugging) [also turns off interface gen]
- /^-hi$/ && do { $ProduceHi = 2; next arg; };
+ /^-hi$/ && do { $HiOnStdout = 1; $ProduceHi = '-hifile='; next arg; };
# _do_ generate an interface; usually used as: -noC -hi
- # NB: magic value "2" for $ProduceHi (hack)
- /^-nohi$/ && do { $ProduceHi = 0; next arg; };
+ /^-nohi$/ && do { $ProduceHi = '-nohifile='; next arg; };
# don't generate an interface (even if generating C)
- /^-hi-diffs$/ && do { $HiDiff_flag = 1; next arg; };
- # show diffs if the interface file changes
+ /^-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; };
+ # show/disable diffs if the interface file changes
/^-E$/ && do { push(@CcBoth_flags, '-E');
$Only_preprocess_C = 1;
/^-no-link-chk$/ && do { $LinkChk = 0; next arg; };
# don't do consistency-checking after a link
- # generate code for a different target architecture; e.g., m68k
- # ToDo: de-Glasgow-ize & probably more...
-# OLD:
-# /^-target$/ && do { $TargetPlatform = &grab_arg_arg('-target', '');
-# if ($TargetPlatform ne $HostPlatform) {
-# if ( $TargetPlatform =~ /^m68k-/ ) {
-# $CcUnregd = $CcRegd = 'gcc-m68k';
-# } else {
-# print STDERR "$Pgm: Can't handle -target $TargetPlatform\n";
-# $Status++;
-# }
-# }
-# next arg; };
-
- /^-unregisteri[sz]ed$/ && do { $RegisteriseC = 'no';
- $ProduceC = 1; $ProduceS = ''; # via C, definitely
- next arg; };
-
/^-tmpdir$/ && do { $Tmp_prefix = &grab_arg_arg('-tmpdir', '');
$Tmp_prefix = "$Tmp_prefix/ghc$$";
$ENV{'TMPDIR'} = $Tmp_prefix; # for those who use it...
# "-o -" sends it to stdout
# if <file> has a directory component, that dir must already exist
+ /^-odir$/ && do { $Specific_output_dir = &grab_arg_arg('-odir', '');
+ if (! -d $Specific_output_dir) {
+ print STDERR "$Pgm: -odir: no such directory: $Specific_output_dir\n";
+ $Status++;
+ }
+ next arg; };
+
/^-o$/ && do { $Specific_output_file = &grab_arg_arg('-o', '');
if ($Specific_output_file ne '-'
&& $Specific_output_file =~ /(.*)\/[^\/]*$/) {
}
next arg; };
+ # NB: -isuf not documented yet (because it doesn't work yet)
+ /^-isuf$/ && do { $Isuffix = &grab_arg_arg('-isuf', '');
+ if ($Isuffix =~ /\./ ) {
+ print STDERR "$Pgm: -isuf suffix shouldn't contain a .\n";
+ $Status++;
+ }
+ next arg; };
+
+ /^-osuf$/ && do { $Osuffix = &grab_arg_arg('-osuf', '');
+ if ($Osuffix =~ /\./ ) {
+ print STDERR "$Pgm: -osuf suffix shouldn't contain a .\n";
+ $Status++;
+ }
+ next arg; };
+
# -ohi <file>; send the interface to <file>; "-ohi -" to send to stdout
/^-ohi$/ && do { $Specific_hi_file = &grab_arg_arg('-ohi', '');
if ($Specific_hi_file ne '-'
}
next arg; };
+ /^-hisuf$/ && do { $HiSuffix = &grab_arg_arg('-hisuf', '');
+ if ($HiSuffix =~ /\./ ) {
+ print STDERR "$Pgm: -hisuf suffix shouldn't contain a .\n";
+ $Status++;
+ }
+ next arg; };
+ /^-hisuf-prelude$/ && do { # as esoteric as they come...
+ $SysHiSuffix = &grab_arg_arg('-hisuf-prelude', '');
+ if ($SysHiSuffix =~ /\./ ) {
+ print STDERR "$Pgm: -hisuf-prelude suffix shouldn't contain a .\n";
+ $Status++;
+ }
+ next arg; };
+
/^-odump$/ && do { $Specific_dump_file = &grab_arg_arg('-odump', '');
if ($Specific_dump_file =~ /(.*)\/[^\/]*$/) {
local($dir_part) = $1;
}
next arg; };
- /^-odir$/ && do { $Specific_output_dir = &grab_arg_arg('-odir', '');
- if (! -d $Specific_output_dir) {
- print STDERR "$Pgm: -odir: no such directory: $Specific_output_dir\n";
- $Status++;
- }
- next arg; };
-
- /^-osuf$/ && do { $Osuffix = &grab_arg_arg('-osuf', ''); next arg; };
- /^-hisuf$/ && do { $HiSuffix = &grab_arg_arg('-hisuf', '');
- push(@HsP_flags, "-h$HiSuffix");
- next arg; };
-
- /^-hisuf-prelude$/ && do { # as esoteric as they come...
- local($suffix) = &grab_arg_arg('-hisuf-prelude', '');
- push(@HsP_flags, "-g$suffix");
- next arg; };
-
#-------------- scc & Profiling Stuff ----------------------------------
/^-prof$/ && do { $PROFing = 'p'; next arg; }; # profiling -- details later!
- /^-fheap-profiling-with-age$/ && do {
- $PROFaging = 'a';
- push(@CcBoth_flags, '-DHEAP_PROF_WITH_AGE');
- next arg; };
-
/^-auto/ && do {
# generate auto SCCs on top level bindings
# -auto-all = all top level bindings
$PROFcaf = '-fauto-sccs-on-individual-cafs';
next arg; };
-# UNUSED:
-# /^-dict-all/ && do { # generate individual SCC annotations on dictionaries
-# $PROFdict = '-fauto-sccs-on-individual-dicts';
-# next arg; };
-
/^-ignore-scc$/ && do {
# forces ignore of scc annotations even if profiling
$PROFignore_scc = '-W';
next arg; };
- /^-G(.*)$/ && do { push(@HsC_flags, $_); # set group for cost centres
+ /^-G(.*)$/ && do { push(@HsC_flags, "-G=$1"); # set group for cost centres
next arg; };
+ /^-unprof-scc-auto/ && do {
+ # generate auto SCCs on top level bindings when not profiling
+ # used to measure optimisation effects of presence of sccs
+ $UNPROFscc_auto = ( /-all/ )
+ ? '-fauto-sccs-on-all-toplevs'
+ : '-fauto-sccs-on-exported-toplevs';
+ next arg; };
+
#--------- ticky/concurrent/parallel -----------------------------------
# we sort out the details a bit later on
#-------------- "user ways" --------------------------------------------
- (/^-user-setup-([a-o])$/
+ (/^-user-setup-([a-oA-Z])$/
|| /^$(GHC_BUILD_FLAG_a)$/
|| /^$(GHC_BUILD_FLAG_b)$/
|| /^$(GHC_BUILD_FLAG_c)$/
|| /^$(GHC_BUILD_FLAG_m)$/
|| /^$(GHC_BUILD_FLAG_n)$/
|| /^$(GHC_BUILD_FLAG_o)$/
+ || /^$(GHC_BUILD_FLAG_A)$/
+ || /^$(GHC_BUILD_FLAG_B)$/
|| /^$(GHC_BUILD_FLAG_2s)$/ # GC ones...
|| /^$(GHC_BUILD_FLAG_1s)$/
|| /^$(GHC_BUILD_FLAG_du)$/
) && do {
- /^-user-setup-([a-o])$/ && do { $BuildTag = "_$1"; };
+ /^-user-setup-([a-oA-Z])$/ && do { $BuildTag = "_$1"; };
/^$(GHC_BUILD_FLAG_a)$/ && do { $BuildTag = '_a'; };
/^$(GHC_BUILD_FLAG_b)$/ && do { $BuildTag = '_b'; };
/^$(GHC_BUILD_FLAG_m)$/ && do { $BuildTag = '_m'; };
/^$(GHC_BUILD_FLAG_n)$/ && do { $BuildTag = '_n'; };
/^$(GHC_BUILD_FLAG_o)$/ && do { $BuildTag = '_o'; };
+ /^$(GHC_BUILD_FLAG_A)$/ && do { $BuildTag = '_A'; };
+ /^$(GHC_BUILD_FLAG_B)$/ && do { $BuildTag = '_B'; };
/^$(GHC_BUILD_FLAG_2s)$/ && do { $BuildTag = '_2s'; };
/^$(GHC_BUILD_FLAG_1s)$/ && do { $BuildTag = '_1s'; };
/^-syslib(.*)/ && do { local($syslib) = &grab_arg_arg('-syslib',$1);
print STDERR "$Pgm: no such system library (-syslib): $syslib\n",
- $Status++ unless $syslib =~ /^(hbc|ghc|contrib)$/;
+ $Status++ unless $syslib =~ /^(hbc|ghc|posix|contrib)$/;
unshift(@SysImport_dir,
$(INSTALLING)
- ? "$InstDataDirGhc/imports/$syslib"
- : "$TopPwd/$(CURRENT_DIR)/$(GHC_LIBSRC)/$syslib");
+ ? "$InstSysLibDir/$syslib/imports"
+ : "$TopPwd/hslibs/$syslib/src");
+
+ if (! $(INSTALLING)) {
+ push(@SysLibrary_dir,
+ ("$TopPwd/hslibs/$syslib"
+ ,"$TopPwd/hslibs/$syslib/cbits"));
+ }
- unshift(@SysLibrary, ('-lHS' . $syslib ));
+ push(@SysLibrary, ("-lHS$syslib"
+ ,"-lHS${syslib}_cbits"));
next arg; };
# these change what executable is run for each phase:
/^-pgmL(.*)$/ && do { $Unlit = $1; next arg; };
/^-pgmP(.*)$/ && do { $HsCpp = $1; next arg; };
- /^-pgmp(.*)$/ && do { $HsP = $1; next arg; };
/^-pgmC(.*)$/ && do { $HsC = $1; next arg; };
- /^-pgmcO(.*)$/ && do { $CcRegd = $1; next arg; };
- /^-pgmc(.*)$/ && do { $CcUnregd = $1; next arg; };
+ /^-pgmcO?(.*)$/ && do { $CcRegd = $1; next arg; }; # the O? for back compat
/^-pgma(.*)$/ && do { $As = $1; next arg; };
/^-pgml(.*)$/ && do { $Lnkr = $1; next arg; };
# these allow arbitrary option-strings to go to any phase:
/^-optL(.*)$/ && do { push(@Unlit_flags, $1); next arg; };
/^-optP(.*)$/ && do { push(@HsCpp_flags, $1); next arg; };
- /^-optp(.*)$/ && do { push(@HsP_flags, $1); next arg; };
/^-optCrts(.*)$/&& do { push(@HsC_rts_flags, $1); next arg; };
/^-optC(.*)$/ && do { push(@HsC_flags, $1); next arg; };
- /^-optcNhc(.*)$/ && do { push(@CcUnregd_flags_hc,$1); next arg; };
- /^-optcNc(.*)$/ && do { push(@CcUnregd_flags_c,$1); next arg; };
- /^-optcN(.*)$/ && do { push(@CcUnregd_flags, $1); next arg; };
- /^-optcOhc(.*)$/&& do { push(@CcRegd_flags_hc,$1); next arg; };
- /^-optcOc(.*)$/ && do { push(@CcRegd_flags_c, $1); next arg; };
- /^-optcO(.*)$/ && do { push(@CcRegd_flags, $1); next arg; };
/^-optc(.*)$/ && do { push(@CcBoth_flags, $1); next arg; };
/^-opta(.*)$/ && do { push(@As_flags, $1); next arg; };
/^-optl(.*)$/ && do { push(@Ld_flags, $1); next arg; };
/^-D(.*)/ && do { push(@HsCpp_flags, "'-D".&grab_arg_arg('-D',$1)."'"); next arg; };
/^-U(.*)/ && do { push(@HsCpp_flags, "'-U".&grab_arg_arg('-U',$1)."'"); next arg; };
- #---------- Haskell parser (hsp) ---------------------------------------
- /^-ddump-parser$/ && do { $Dump_parser_output = 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-insn-counts$/ && do { $Dump_asm_insn_counts = 1; next arg; };
- /^-ddump-asm-globals-info$/ && do { $Dump_asm_globals_info = 1; next arg; };
-
+ /^-ddump-raw-asm$/ && do { $Dump_raw_asm = 1; next arg; };
/^-ddump-asm-splitting-info$/ && do { $Dump_asm_splitting_info = 1; next arg; };
#---------- Haskell compiler (hsc) -------------------------------------
-# possibly resurrect LATER
-# /^-fspat-profiling$/ && do { push(@HsC_flags, '-fstg-reduction-counts');
-# $ProduceS = ''; $ProduceC = 1; # must use C compiler
-# push(@CcBoth_flags, '-DDO_SPAT_PROFILING');
-# push(@CcBoth_flags, '-fno-schedule-insns'); # not essential
-# next arg; };
-
/^-keep-hc-files?-too$/ && do { $Keep_hc_file_too = 1; next arg; };
/^-keep-s-files?-too$/ && do { $Keep_s_file_too = 1; next arg; };
- /^-fhaskell-1\.3$/ && do { $haskell1_version = 3;
- push(@HsP_flags, '-3');
- push(@HsC_flags, $_);
- $TopClosureFile =~ s/TopClosureXXXX/TopClosure13XXXX/;
- unshift(@SysImport_dir,
- $(INSTALLING)
- ? "$InstDataDirGhc/imports/haskell-1.3"
- : "$TopPwd/$(CURRENT_DIR)/$(GHC_LIBSRC)/haskell-1.3");
+ /^-fhaskell-1\.3$/ && do { next arg; }; # a no-op right now
- unshift(@SysLibrary, '-lHS13');
+ /^-fignore-interface-pragmas$/ && do { push(@HsC_flags, $_); next arg; };
+ /^-fno-implicit-prelude$/ && do { $NoImplicitPrelude= 1; push(@HsC_flags, $_); next arg; };
+
+ # ToDo: rename to -fcompiling-ghc-internals=<module>
+ # NB: not documented
+ /^-fcompiling-ghc-internals(.*)/ && do { local($m) = &grab_arg_arg('-fcompiling-ghc-internals',$1);
+ push(@HsC_flags, "-fcompiling-ghc-internals=$m");
next arg; };
- /^-fno-implicit-prelude$/ && do { push(@HsP_flags, '-P'); next arg; };
- /^-fignore-interface-pragmas$/ && do { push(@HsP_flags, '-p'); next arg; };
+ # NB: not really put to use and not documented
+ /^-fusing-ghc-internals$/ && do { $UsingGhcInternals = 1; next arg; };
- /^-prelude$/ && do { $CompilingPrelude = 1;
- push(@HsC_flags, $_); next arg; };
+ /^-user-prelude-force/ && do { # ignore if not -user-prelude
+ next arg; };
/^-split-objs(.*)/ && do {
local($sname) = &grab_arg_arg('-split-objs', $1);
$sname =~ s/ //g; # no spaces
- if ( $TargetPlatform =~ /^(sparc|alpha|m68k|mips|i[34]86|hppa1\.1)-/ ) {
+ if ( $TargetPlatform !~ /^(alpha|hppa1\.1|i386|m68k|mips|powerpc|sparc)-/ ) {
+ $SplitObjFiles = 0;
+ print STDERR "WARNING: don't know how to split objects on this platform: $TargetPlatform\n`-split-objs' option ignored\n";
+ } else {
$SplitObjFiles = 1;
- push(@HsC_flags, "-fglobalise-toplev-names$sname");
+ $HscOut = '-C=';
+
+ push(@HsC_flags, "-fglobalise-toplev-names=$sname");
push(@CcBoth_flags, '-DUSE_SPLIT_MARKERS');
require('ghc-split.prl')
|| &tidy_up_and_die(1,"$Pgm: panic: can't load ghc-split.prl!\n");
- } else {
- $SplitObjFiles = 0;
- print STDERR "WARNING: don't know how to split objects on this platform: $TargetPlatform\n`-split-objs' option ignored\n";
}
next arg; };
- /^-fglobalise-toplev-names$/&& do { push(@HsC_flags, $_); next arg; };
-
- /^-f(hide-builtin-names|min-builtin-names)$/
- && do { push(@HsC_flags, $_);
- push(@HsP_flags, '-P'); # don't read Prelude.hi
- push(@HsP_flags, '-N'); # allow foo# names
- next arg; };
- /^-f(glasgow-exts|hide-builtin-instances)$/
+ /^-fglasgow-exts$/
&& do { push(@HsC_flags, $_);
push(@HsP_flags, '-N');
# push(@HsC_flags, '-fshow-import-specs');
- if ( ! $(INSTALLING) ) {
- unshift(@SysImport_dir,
- "$TopPwd/$(CURRENT_DIR)/$(GHC_LIBSRC)/glaExts");
- }
next arg; };
- /^-fspecialise-unboxed$/
- && do { $Oopt_SpecialiseUnboxed = '-fspecialise-unboxed';
+ /^-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; };
+
# 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 = '';
/^-fno-foldr-build-rule$/
&& do { $Oopt_FoldrBuild = 0;
- next arg; };
+ next arg; };
/^-fno-enable-tech$/
&& do { $Oopt_FB_Support = '';
next arg; };
-# /^-ffoldr-build-ww$/
-# && do { $Oopt_FoldrBuildWW = 1; next arg; };
-
-
- /^-fasm-(.*)$/ && do { $ProduceS = $1; $ProduceC = 0; # force using nativeGen
- push(@HsC_flags, $_); # if from the command line
- next arg; };
+ /^-fno-snapback-to-append$/
+ && do { $Oopt_FoldrBuildInline .= ' -fdo-not-fold-back-append ';
+ #print "No Foldback of append\n";
+ next arg; };
- /^-fvia-C$/ && do { $ProduceS = ''; $ProduceC = 1; # force using C compiler
- next arg; };
+ # ---------------
- /^-f(no-)?omit-frame-pointer$/ && do {
- unshift(@CcBoth_flags, ( $_ ));
- next arg; };
+ /^-fasm-(.*)$/ && do { $HscOut = '-S='; next arg; }; # force using nativeGen
+ /^-fvia-C$/ && do { $HscOut = '-C='; next arg; }; # force using C compiler
# ---------------
/^-fdo-monad-eta-expansion$/
&& do { $Oopt_MonadEtaExpansion = $_; next arg; };
-# /^-flambda-lift$/ # so Simon can do some testing; ToDo:rm
-# && do { $Oopt_LambdaLift = $_; 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($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; };
# ---------------
&squashHscFlag("-f$1");
next arg; };
- /^-f/ && do { push(@HsC_flags, $_); next arg; };
+ /^-f(show-import-specs)/
+ && do { push(@HsC_flags, $_); next arg; };
# ---------------
- /^-mlong-calls/ && do { # for GCC for HP-PA boxes
- unshift(@CcBoth_flags, ('-mlong-calls'));
+ /^-mlong-calls$/ && do { # for GCC for HP-PA boxes
+ unshift(@CcBoth_flags, ( $_ ));
next arg; };
- /^-monly-([432])-regs/ && do { # for iX86 boxes only; no effect otherwise
- $StolenX86Regs = $1;
+ /^-m(v8|sparclite|cypress|supersparc|cpu=(cypress|supersparc))$/
+ && do { # for GCC for SPARCs
+ unshift(@CcBoth_flags, ( $_ ));
next arg; };
- /^-mtoggle-sp-mangling/ && do { # for iX86 boxes only; for RTS only
- $SpX86Mangling = 1 - $SpX86Mangling;
+ /^-monly-([432])-regs/ && do { # for iX86 boxes only; no effect otherwise
+ $StolenX86Regs = $1;
next arg; };
#*************** ... and lots of debugging ones (form: -d* )
- /^-darity-checks$/ && do {
- push(@HsC_flags, $_);
- push(@CcBoth_flags, '-D__DO_ARITY_CHKS__');
- next arg; };
- /^-darity-checks-C-only$/ && do {
- # so we'll have arity-checkable .hc files
- # should we decide we need them later...
- push(@HsC_flags, '-darity-checks');
- next arg; };
- /^-dno-stk-checks$/ && do {
- push(@HsC_flags, '-dno-stk-chks');
- push(@CcBoth_flags, '-D__OMIT_STK_CHKS__');
- next arg; };
-
# -d(no-)core-lint is done this way so it is turn-off-able.
/^-dcore-lint/ && do { $CoreLint = '-dcore-lint'; next arg; };
/^-dno-core-lint/ && do { $CoreLint = ''; next arg; };
/^-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; };
+ /^-dsource-stats/ && do { push(@HsC_flags, $_); next arg; };
/^-dsimplifier-stats/ && do { push(@HsC_flags, $_); next arg; };
+ /^-dstg-stats/ && do { $Oopt_StgStats = $_; next arg; };
#*************** ... and now all these -R* ones for its runtime system...
- /^-Rhbc$/ && do { $RTS_style = 'hbc'; next arg; };
- /^-Rghc$/ && do { $RTS_style = 'ghc'; next arg; };
-
/^-Rscale-sizes?(.*)/ && do {
$Scale_sizes_by = &grab_arg_arg('-Rscale-sizes', $1);
next arg; };
if ($heap_size <= 0) {
print STDERR "$Pgm: resetting heap-size to zero!!!\n";
$Specific_heap_size = 0;
- }
+
# if several heap sizes given, take the largest...
- if ($heap_size >= $Specific_heap_size) {
+ } elsif ($heap_size >= $Specific_heap_size) {
$Specific_heap_size = $heap_size;
} else {
print STDERR "$Pgm: ignoring heap-size-setting option ($_)...not the largest seen\n";
if ($stk_size <= 0) {
print STDERR "$Pgm: resetting stack-size to zero!!!\n";
$Specific_stk_size = 0;
- }
+
# if several stack sizes given, take the largest...
- if ($stk_size >= $Specific_stk_size) {
+ } elsif ($stk_size >= $Specific_stk_size) {
$Specific_stk_size = $stk_size;
} else {
print STDERR "$Pgm: ignoring stack-size-setting option (-Rmax-stksize $stk_size)...not the largest seen\n";
/^-Rghc-timing/ && do { $CollectGhcTimings = 1; next arg; };
#---------- C high-level assembler (gcc) -------------------------------
-# OLD: and dangerous
-# /^-g$/ && do { push(@CcBoth_flags, $_); next arg; };
-# /^-(p|pg)$/ && do { push(@CcBoth_flags, $_); push(@Ld_flags, $_); next arg; };
-# /^-(fpic|fPIC)$/ && do { push(@CcBoth_flags, $_); push(@As_flags, $_); next arg; };
-
/^-(Wall|ansi|pedantic)$/ && do { push(@CcBoth_flags, $_); next arg; };
# -dgcc-lint is a useful way of making GCC very fussy.
#---------- mixed cc and linker magic ----------------------------------
# this optimisation stuff is finally sorted out later on...
-# /^-O0$/ && do { # turn all optimisation *OFF*
-# $OptLevel = -1;
-# $ProduceS = ''; $ProduceC = 1; # force use of C compiler
-# next arg; };
-
/^-O2-for-C$/ && do { $MinusO2ForC = 1; next arg; };
/^-O[1-2]?$/ && do {
+# print STDERR "$Pgm: NOTE: this version of GHC doesn't support -O or -O2\n";
local($opt_lev) = ( /^-O2$/ ) ? 2 : 1; # max 'em
$OptLevel = ( $opt_lev > $OptLevel ) ? $opt_lev : $OptLevel;
- if ( $OptLevel == 2 ) { # force use of C compiler
- $ProduceS = ''; $ProduceC = 1;
- }
+ $HscOut = '-C=' if $OptLevel == 2; # force use of C compiler
next arg; };
/^-Onot$/ && do { $OptLevel = 0; next arg; }; # # set it to <no opt>
close(OFILE);
next arg; };
- /^-debug$/ && do { # all this does is mark a .hc/.o as "debugging"
- # in the consistency info
- $DEBUGging = 'd';
- next arg; };
-# OLD: do it another way
-# /^-dgc-debug$/ && do { push(@CcBoth_flags, '-D_GC_DEBUG'); next arg; };
+ /^-debug$/ && do { # all this does is mark a .hc/.o as "debugging"
+ # in the consistency info
+ $DEBUGging = 'd';
+ next arg; };
+
+ #---------- linking .a file --------------------------------------------
+
+ /^-Main(.*)/ && do {
+ # specifies main or mainPrimIO to be linked
+ $Ld_main = $1;
+ next arg; };
#---------- catch unrecognized flags -----------------------------------
next arg; };
#---------- anything else is considered an input file ------------------
- # (well, .o files are immediately queued up as linker fodder..)
- if (/\.o$/) {
+ # (well, .o and .a files are immediately queued up as linker fodder..)
+ if (/\.[oa]$/) {
push(@Link_file, $_);
} else {
push(@Input_file, $_);
if ( ! $PROFing ) {
# warn about any scc exprs found (in case scc used as identifier)
push(@HsP_flags, '-W');
-} else {
- $Oopt_AddAutoSccs = '-fadd-auto-sccs' if $PROFauto;
- $Oopt_FinalStgProfilingMassage = '-fmassage-stg-for-profiling';
+ # add -auto sccs even if not profiling !
+ push(@HsC_flags, $UNPROFscc_auto) if $UNPROFscc_auto;
+
+} else {
push(@HsC_flags, $PROFauto) if $PROFauto;
push(@HsC_flags, $PROFcaf) if $PROFcaf;
-#UNUSED: push(@HsC_flags, $PROFdict) if $PROFdict;
+ #push(@HsC_flags, $PROFdict) if $PROFdict;
+
+ $Oopt_FinalStgProfilingMassage = '-fmassage-stg-for-profiling';
push(@HsP_flags, (($PROFignore_scc) ? $PROFignore_scc : '-S'));
- if ($SplitObjFiles && ! $CompilingPrelude) {
+ if ( $SplitObjFiles ) {
# can't split with cost centres -- would need global and externs
print STDERR "$Pgm: WARNING: splitting objects when profiling will *BREAK* if any _scc_s are present!\n";
# (but it's fine if there aren't any _scc_s around...)
\end{description}
\begin{code}
-# OLD:
-#@HsC_minusO0_flags
-# = ( $Oopt_AddAutoSccs,
-# '-fsimplify', # would rather *not* run the simplifier (ToDo)
-# '\(', '\)', # nothing special at all ????
-#
-# $Oopt_FinalStgProfilingMassage
-# );
-
@HsC_minusNoO_flags
= ( '-fsimplify',
'\(',
- "$Oopt_FB_Support",
- '-falways-float-lets-from-lets',
+ $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
+ $Oopt_PedanticBottoms,
+# $Oopt_MonadEtaExpansion, # no thanks
'-fsimpl-uf-use-threshold0',
'-fessential-unfoldings-only',
-# "$Oopt_UnfoldingUseThreshold", # no thanks
- "$Oopt_MaxSimplifierIterations",
+# $Oopt_UnfoldingUseThreshold, # no thanks
+ $Oopt_MaxSimplifierIterations,
'\)',
$Oopt_AddAutoSccs,
# '-ffull-laziness', # removed 95/04 WDP following Andr\'e's lead
- '-fuse-get-mentioned-vars', # for the renamer
$Oopt_FinalStgProfilingMassage
);
@HsC_minusO_flags # NOTE: used for *both* -O and -O2 (some conditional bits)
= (
- # core2core passes
# initial simplify: mk specialiser happy: minimum effort please
'-fsimplify',
'\(',
- "$Oopt_FB_Support",
- '-fkeep-spec-pragma-ids',
+ $Oopt_FB_Support,
+ '-fkeep-spec-pragma-ids', # required before specialisation
'-fsimpl-uf-use-threshold0',
'-fessential-unfoldings-only',
'-fmax-simplifier-iterations1',
- "$Oopt_PedanticBottoms",
+ $Oopt_PedanticBottoms,
'\)',
- $Oopt_AddAutoSccs, # dangerous to do with *no* simplification...
-
- '-fspecialise-overloaded',
- $Oopt_SpecialiseUnboxed,
- '-fspecialise',
+ ($Oopt_DoSpecialise) ? (
+ '-fspecialise-overloaded',
+ $Oopt_SpecialiseUnboxed,
+ $Oopt_DoSpecialise,
+ ) : (),
- '-fsimplify', # need tossing before calc-i...
- '\(',
- "$Oopt_FB_Support",
+ '-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',
-# '-flet-to-case', # no point, before strictness analysis
- "$Oopt_PedanticBottoms",
- "$Oopt_MonadEtaExpansion",
- "$Oopt_UnfoldingUseThreshold",
- "$Oopt_MaxSimplifierIterations",
+ $Oopt_PedanticBottoms,
+ $Oopt_MonadEtaExpansion,
+ $Oopt_UnfoldingUseThreshold,
+ $Oopt_MaxSimplifierIterations,
'\)',
- '-fcalc-inlinings1',
+#LATER: '-fcalc-inlinings1', -- pointless for 2.01
# ($Oopt_FoldrBuildWW) ? (
# '-ffoldr-build-ww-anal',
# '-ffoldr-build-worker-wrapper',
# '-fsimplify',
# '\(',
-# "$Oopt_FB_Support",
+# $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', # no point, before strictness analysis
-# "$Oopt_PedanticBottoms",
-# "$Oopt_MonadEtaExpansion",
-# "$Oopt_UnfoldingUseThreshold",
-# "$Oopt_MaxSimplifierIterations",
+# $Oopt_PedanticBottoms,
+# $Oopt_MonadEtaExpansion,
+# $Oopt_UnfoldingUseThreshold,
+# $Oopt_MaxSimplifierIterations,
# '\)',
# ) : (),
'-ffull-laziness',
($Oopt_FoldrBuild) ? (
+ '-ffoldr-build-on', # desugar list comprehensions for foldr/build
+
'-fsimplify',
'\(',
'-fignore-inline-pragma', # **** NB!
'-fdo-foldr-build', # NB
- "$Oopt_FB_Support",
+ $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', # no point, before strictness analysis
- "$Oopt_PedanticBottoms",
- "$Oopt_MonadEtaExpansion",
- "$Oopt_UnfoldingUseThreshold",
- "$Oopt_MaxSimplifierIterations",
+ $Oopt_PedanticBottoms,
+ $Oopt_MonadEtaExpansion,
+ $Oopt_UnfoldingUseThreshold,
+ $Oopt_MaxSimplifierIterations,
'\)',
) : (),
'-fsimplify',
'\(',
- "$Oopt_FB_Support",
+ $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', # no point, before strictness analysis
- '-fdo-inline-foldr-build',
- # you need to inline foldr!
- "$Oopt_PedanticBottoms",
- "$Oopt_MonadEtaExpansion",
- "$Oopt_UnfoldingUseThreshold",
- "$Oopt_MaxSimplifierIterations",
+ ($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,
'\)',
'-fstrictness',
'-fsimplify',
'\(',
- "$Oopt_FB_Support",
+ $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!
- "$Oopt_PedanticBottoms",
- "$Oopt_MonadEtaExpansion",
- "$Oopt_UnfoldingUseThreshold",
- "$Oopt_MaxSimplifierIterations",
+ '-flet-to-case', # Aha! Only done after strictness analysis
+ $Oopt_PedanticBottoms,
+ $Oopt_MonadEtaExpansion,
+ $Oopt_UnfoldingUseThreshold,
+ $Oopt_MaxSimplifierIterations,
'\)',
'-ffloat-inwards',
# ( ($OptLevel != 2)
# ? ''
-# : "-fliberate-case -fsimplify \\( "$Oopt_FB_Support" -ffloat-lets-exposing-whnf -ffloat-primops-ok -fcase-of-case -fdo-case-elim -fdo-eta-reduction -fdo-lambda-eta-expansion -freuse-con -flet-to-case $Oopt_PedanticBottoms $Oopt_MonadEtaExpansion $Oopt_UnfoldingUseThreshold $Oopt_MaxSimplifierIterations \\)" ),
+# : "-fliberate-case -fsimplify \\( $Oopt_FB_Support -ffloat-lets-exposing-whnf -ffloat-primops-ok -fcase-of-case -fdo-case-elim -fcase-merge -fdo-eta-reduction -fdo-lambda-eta-expansion -freuse-con -flet-to-case $Oopt_PedanticBottoms $Oopt_MonadEtaExpansion $Oopt_UnfoldingUseThreshold $Oopt_MaxSimplifierIterations \\)" ),
# Final clean-up simplification:
'-fsimplify',
'\(',
- "$Oopt_FB_Support",
+ $Oopt_FB_Support,
'-ffloat-lets-exposing-whnf',
'-ffloat-primops-ok',
'-fcase-of-case',
'-fdo-case-elim',
+ '-fcase-merge',
'-fdo-eta-reduction',
'-fdo-lambda-eta-expansion',
'-freuse-con',
'-flet-to-case',
'-fignore-inline-pragma', # **** NB!
- '-fdo-inline-foldr-build', # NB
- "$Oopt_PedanticBottoms",
- "$Oopt_MonadEtaExpansion",
- "$Oopt_UnfoldingUseThreshold",
- "$Oopt_MaxSimplifierIterations",
+ $Oopt_FoldrBuildInline,
+ ($Oopt_FoldrBuild) ? ('-fdo-foldr-build') : (),
+ # but still do reductions if you see them!
+ $Oopt_PedanticBottoms,
+ $Oopt_MonadEtaExpansion,
+ $Oopt_UnfoldingUseThreshold,
+ $Oopt_MaxSimplifierIterations,
'\)',
-# '-fstatic-args',
- '-fcalc-inlinings2',
+ # '-fstatic-args',
+
+#LATER: '-fcalc-inlinings2', -- pointless for 2.01
# stg2stg passes
- '-fupdate-analysis',
+#LATER: '-fupdate-analysis',
'-flambda-lift',
$Oopt_FinalStgProfilingMassage,
+ $Oopt_StgStats,
# flags for stg2stg
'-flet-no-escape',
- # how do we desugar list comprehensions ?
- (($Oopt_FoldrBuild) ? '-ffoldr-build-on' : '' ),
-
# SPECIAL FLAGS for -O2
- (($OptLevel == 2) ? '-fsemi-tagging' : '')
+ ($OptLevel == 2) ? (
+ '-fsemi-tagging',
+ ) : (),
);
\end{code}
Sort out what we're going to do about optimising. First, the @hsc@
flags and regular @cc@ flags to worry about:
\begin{code}
-#if ( $OptLevel < 0 ) {
-
-# &add_Hsc_flags( @HsC_minusO0_flags );
-
if ( $OptLevel <= 0 ) {
# for this level, we tell the parser -fignore-interface-pragmas
- push(@HsP_flags, '-p');
+ push(@HsC_flags, '-fignore-interface-pragmas');
# and tell the compiler not to produce them
push(@HsC_flags, '-fomit-interface-pragmas');
%************************************************************************
%* *
-\subsection{Check for registerising, consistency, etc.}
+\subsection{Check for consistency, etc.}
%* *
%************************************************************************
-Are we capable of generating ``registerisable'' C (either using
-C or via equivalent native code)?
-
-\begin{code}
-$RegisteriseC = ( $GccAvailable
- && $RegisteriseC ne 'no' # not explicitly *un*set...
- && ($TargetPlatform =~ /^(alpha|hppa1\.1|i[34]86|m68k|mips|sparc)-/)
- ) ? 'o' : '';
-\end{code}
-
Sort out @$BuildTag@, @$PROFing@, @$CONCURing@, @$PARing@,
@$GRANing@, @$TICKYing@:
\begin{code}
if ( $BuildTag ne '' ) {
local($b) = $BuildDescr{$BuildTag};
- if ($PROFing eq 'p') { print STDERR "$Pgm: Can't mix $b with profiling.\n"; exit 1; }
if ($CONCURing eq 'c') { print STDERR "$Pgm: Can't mix $b with -concurrent.\n"; exit 1; }
if ($PARing eq 'p') { print STDERR "$Pgm: Can't mix $b with -parallel.\n"; exit 1; }
if ($GRANing eq 'g') { print STDERR "$Pgm: Can't mix $b with -gransim.\n"; exit 1; }
if ($TICKYing eq 't') { print STDERR "$Pgm: Can't mix $b with -ticky.\n"; exit 1; }
+ # ok to have a user-way profiling build
+ # eval the profiling opts ... but leave user-way BuildTag
+ if ($PROFing eq 'p') { eval($EvaldSetupOpts{'_p'}); }
+
} elsif ( $PROFing eq 'p' ) {
if ($PARing eq 'p') { print STDERR "$Pgm: Can't do profiling with -parallel.\n"; exit 1; }
if ($GRANing eq 'g') { print STDERR "$Pgm: Can't do profiling with -gransim.\n"; exit 1; }
\begin{code}
if ( $BuildTag ne '' ) { # something other than normal sequential...
- push(@HsP_flags, "-g$BuildTag.hi"); # use appropriate Prelude .hi files
+ push(@HsP_flags, "-syshisuffix=$BuildTag.hi"); # use appropriate Prelude .hi files
- $ProduceC = 1; $ProduceS = ''; # must go via C
-
-# print STDERR "eval...",$EvaldSetupOpts{$BuildTag},"\n";
+ $HscOut = '-C='; # must go via C
eval($EvaldSetupOpts{$BuildTag});
}
Decide what the consistency-checking options are in force for this run:
\begin{code}
$HsC_consist_options = "${BuildTag},${DEBUGging}";
-$Cc_consist_options = "${BuildTag},${DEBUGging},${RegisteriseC}";
+$Cc_consist_options = "${BuildTag},${DEBUGging}";
\end{code}
%************************************************************************
Note: a few ``always apply'' flags were set at the very beginning.
\begin{code}
-if ($TargetPlatform =~ /^m68k-/) {
+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
+ # needed for very big modules (sigh), and we don't want
+ # to hobble ourselves further on all the other modules
+ # (most of them).
+ unshift(@CcBoth_flags, ('-D_HPUX_SOURCE'));
+ # ___HPUX_SOURCE, not _HPUX_SOURCE, is #defined if -ansi!
+ # (very nice, but too bad the HP /usr/include files don't agree.)
+
+} elsif ($TargetPlatform =~ /^i386-/) {
+ # we know how to *mangle* asm for X86
+ unshift(@CcRegd_flags, ('-D__STG_REV_TBLS__'));
+ unshift(@CcRegd_flags, ('-DSTACK_CHECK_BY_PAGE_FAULT=1')) if $StkChkByPageFaultOK;
+
+ # -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.
+
+ unshift(@CcRegd_flags_hc, '-fno-defer-pop');
+ unshift(@CcRegd_flags, '-fomit-frame-pointer');
+ unshift(@CcRegd_flags, "-DSTOLEN_X86_REGS=$StolenX86Regs");
+
+} elsif ($TargetPlatform =~ /^m68k-/) {
# we know how to *mangle* asm for m68k
unshift (@CcRegd_flags, ('-D__STG_REV_TBLS__'));
unshift (@CcRegd_flags, ('-DSTACK_CHECK_BY_PAGE_FAULT=1')) if $StkChkByPageFaultOK;
# maybe gives reg alloc a better time
# also: -fno-defer-pop is not sufficiently well-behaved without it
-} elsif ($TargetPlatform =~ /^i[34]86-/) {
- # we know how to *mangle* asm for X86
+} 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(@CcRegd_flags, ('-m486')); # not worth not doing
+ unshift(@CcBoth_flags, ('-static'));
- # -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.
-
- unshift(@CcRegd_flags_hc, '-fno-defer-pop');
- unshift(@CcRegd_flags, '-fomit-frame-pointer');
- unshift(@CcRegd_flags, "-DSTOLEN_X86_REGS=$StolenX86Regs");
- unshift(@CcRegd_flags_hc, "-DMANGLING_X86_SP=$SpX86Mangling"); # only used for checking
- # the mangler will insert patch-up code if $StolenX86Regs != 5.
- # *** HACK *** of the worst sort.
- unshift(@CcBoth_flags, ('-static')) if $GccAvailable; # maybe unnecessary???
-
-} elsif ($TargetPlatform =~ /^sparc-/) {
- # we know how to *mangle* asm for SPARC
+} 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;
+ unshift(@CcBoth_flags, ('-static')); # always easier to start with
+ unshift(@CcRegd_flags, ('-finhibit-size-directive')); # avoids traceback tables
-} elsif ($TargetPlatform =~ /^alpha-/) {
- # we know how to *mangle* asm for alpha
+} 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;
- unshift(@CcBoth_flags, ('-static')) if $GccAvailable;
-} elsif ($TargetPlatform =~ /^hppa/) {
- # we know how to *mangle* asm for hppa
- unshift(@CcRegd_flags, ('-D__STG_REV_TBLS__'));
- unshift(@CcBoth_flags, ('-static')) if $GccAvailable;
- # We don't put in '-mlong-calls', because it's only
- # needed for very big modules (sigh), and we don't want
- # to hobble ourselves further on all the other modules
- # (most of them).
- unshift(@CcBoth_flags, ('-D_HPUX_SOURCE')) if $GccAvailable;
- # ___HPUX_SOURCE, not _HPUX_SOURCE, is #defined if -ansi!
- # (very nice, but too bad the HP /usr/include files don't agree.)
-
-} elsif ($TargetPlatform =~ /^mips-/) {
- # we (hope to) know how to *mangle* asm for MIPSen
- unshift(@CcRegd_flags, ('-D__STG_REV_TBLS__'));
- unshift(@CcRegd_flags, ('-DSTACK_CHECK_BY_PAGE_FAULT=1')) if $StkChkByPageFaultOK;
- unshift(@CcBoth_flags, ('-static')) if $GccAvailable;
}
\end{code}
not an architecture test. (JSM)
\begin{code}
+$Under = ( $TargetPlatform =~ /^alpha-/
+ || $TargetPlatform =~ /^hppa/
+ || $TargetPlatform =~ /^mips-sgi-irix/
+ || $TargetPlatform =~ /^powerpc-/
+ || $TargetPlatform =~ /-solaris/
+ || $TargetPlatform =~ /-linux$/
+ )
+ ? '' : '_';
+
unshift(@Ld_flags,
- ( $TargetPlatform =~ /^alpha-/
- || $TargetPlatform =~ /^mips-sgi-irix/
- || $TargetPlatform =~ /^hppa/
- || $TargetPlatform =~ /-solaris/
- )
- ? ('-u', 'unsafePerformPrimIO_fast1',
- '-u', 'Nil_closure',
- '-u', 'IZh_static_info',
- '-u', 'False_inregs_info',
- '-u', 'True_inregs_info',
- '-u', 'CZh_static_info')
-
- # non-Alphas:
- : ('-u', '_unsafePerformPrimIO_fast1',
- '-u', '_Nil_closure',
- '-u', '_IZh_static_info',
- '-u', '_False_inregs_info',
- '-u', '_True_inregs_info',
- '-u', '_CZh_static_info')
- );
+ (($Ld_main) ? (
+ '-u', "${Under}Main_" . $Ld_main . '_closure',
+ ) : (),
+ '-u', "${Under}GHCbase_unsafePerformPrimIO_fast1",
+ '-u', "${Under}Prelude_Z91Z93_closure", # i.e., []
+ '-u', "${Under}Prelude_IZh_static_info",
+ '-u', "${Under}Prelude_False_inregs_info",
+ '-u', "${Under}Prelude_True_inregs_info",
+ '-u', "${Under}Prelude_CZh_static_info",
+ '-u', "${Under}DEBUG_REGS"))
+ ; # just for fun, now...
\end{code}
%************************************************************************
\begin{code}
# default includes must be added AFTER option processing
-if ( $(INSTALLING) ) {
+if ( ! $(INSTALLING) ) {
+ push (@Include_dir, "$TopPwd/$(CURRENT_DIR)/$(GHC_INCLUDESRC)");
+} else {
push (@Include_dir, "$InstLibDirGhc/includes");
push (@Include_dir, "$InstDataDirGhc/includes");
-
-} else {
- push (@Include_dir, "$TopPwd/$(CURRENT_DIR)/$(GHC_INCLUDESRC)");
}
\end{code}
\begin{code}
+push(@SysLibrary, ( '-lHS', '-lHS_cbits' )); # basic I/O and prelude stuff
+
local($f);
foreach $f (@SysLibrary) {
- $f .= "${BuildTag}" if $f =~ /^-lHS/;
+ next if $f =~ /_cbits/;
+ $f .= $BuildTag if $f =~ /^-lHS/;
}
# fiddle the TopClosure file name...
$Specific_heap_size = $Specific_heap_size * $Scale_sizes_by;
push(@HsC_rts_flags, '-H'.$Specific_heap_size);
$Specific_stk_size = $Specific_stk_size * $Scale_sizes_by;
-push(@HsC_rts_flags, (($RTS_style eq 'ghc') ? '-K' : '-A').$Specific_stk_size);
+push(@HsC_rts_flags, "-K$Specific_stk_size");
# hack to avoid running hscpp
$HsCpp = $Cat if ! $Cpp_flag_set;
mainly for debugging.
\begin{code}
if ($#Input_file < 0 && $#Link_file < 0) {
- push(@Input_file, '-');
+ @Input_file = ( '-' );
+
+ open(INF, "> $Tmp_prefix.hs") || &tidy_up_and_die(1,"Can't open $Tmp_prefix.hs\n");
+ print STDERR "Enter your Haskell program, end with ^D (on a line of its own):\n";
+ while (<>) { print INF $_; }
+ close(INF) || &tidy_up_and_die(1,"Failed writing to $Tmp_prefix.hs\n");
}
\end{code}
Tell the world who we are, if they asked.
\begin{code}
-if ($Verbose) {
- print STDERR "$(PROJECTNAME), version $(PROJECTVERSION) $(PROJECTPATCHLEVEL)\n";
-}
+print STDERR "$(PROJECTNAME), version $(PROJECTVERSION) $(PROJECTPATCHLEVEL)\n"
+ if $Verbose;
\end{code}
%************************************************************************
Link if appropriate.
\begin{code}
if ($Do_lnkr) {
- local($libdirs);
+ local($libdirs) = '';
+
# glue them together:
push(@UserLibrary_dir, @SysLibrary_dir);
- if ($#UserLibrary_dir < 0) {
- $libdirs = '';
- } else {
- $libdirs = '-L' . join(' -L',@UserLibrary_dir);
- }
+
+ $libdirs = '-L' . join(' -L',@UserLibrary_dir) if $#UserLibrary_dir >= 0;
+
# for a linker, use an explicitly given one, or the going C compiler ...
- local($lnkr) = ( $Lnkr ) ? $Lnkr : ($RegisteriseC ? $CcRegd : $CcUnregd );
+ local($lnkr) = ( $Lnkr ) ? $Lnkr : $CcRegd;
- local($output)= ($Specific_output_file ne '') ? "-o $Specific_output_file" : '';
- @Files_to_tidy = ( ($Specific_output_file ne '') ? "$Specific_output_file" : 'a.out' );
+ local($output) = ($Specific_output_file ne '') ? "-o $Specific_output_file" : '';
+ @Files_to_tidy = ($Specific_output_file ne '') ? $Specific_output_file : 'a.out';
local($to_do) = "$lnkr $Verbose @Ld_flags $output @Link_file $TopClosureFile $libdirs @UserLibrary @SysLibrary";
&run_something($to_do, 'Linker');
$pvm_executable = $ENV{'PVM_ROOT'} . '/bin/' . $ENV{'PVM_ARCH'}
. "/$pvm_executable";
- &run_something("rm -f $pvm_executable; cp -p $executable $pvm_executable && rm -f $executable", 'Moving binary to PVM land');
+ &run_something("$Rm -f $pvm_executable; $Cp -p $executable $pvm_executable && $Rm -f $executable", 'Moving binary to PVM land');
# OK, now create the magic script for "$executable"
open(EXEC, "> $executable") || &tidy_up_and_die(1,"$Pgm: couldn't open $executable to write!\n");
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)/ ) {
+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
}
}
-exec "$SysMan $debug $nprocessors @nonPVM_args";
-print STDERR "Exec failed!!!: $SysMan $debug $nprocessors @nonPVM_args\n";
-exit(1);
+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";
+ chmod 0755, $executable;
}
}
\begin{code}
sub ProcessInputFile {
- local($ifile) = @_; # input file name
- local($ifile_root); # root of or basename of input file
- local($ifile_root_file); # non-directory part of $ifile_root
+ local($ifile) = @_; # input file name
+ local($ifile_root); # root of or basename of input file
+ local($ofile_target); # ultimate output file we hope to produce
+ # from input file (need to know for recomp
+ # checking purposes)
+ local($hifile_target);# ditto (but .hi file)
\end{code}
Handle the weirdity of input from stdin.
\begin{code}
- if ($ifile eq '-') {
- open(INF, "> $Tmp_prefix.hs") || &tidy_up_and_die(1,"Can't open $Tmp_prefix.hs\n");
- print STDERR "Enter your Haskell program, end with ^D (on a line of its own):\n";
- while (<>) { print INF $_; }
- close(INF) || &tidy_up_and_die(1,"Failed writing to $Tmp_prefix.hs\n");
- $ifile = "$Tmp_prefix.hs";
- $ifile_root = '_stdin';
- $ifile_root_file = $ifile_root;
+ if ($ifile ne '-') {
+ ($ifile_root = $ifile) =~ s/\.[^\.\/]+$//;
+ $ofile_target = # may be reset later...
+ ($Specific_output_file ne '' && ! $Do_lnkr)
+ ? $Specific_output_file
+ : &odir_ify($ifile_root, 'o');
+ $hifile_target= ($Specific_hi_file ne '')
+ ? $Specific_hi_file
+ : "$ifile_root.$HiSuffix"; # ToDo: odirify?
+ # NB: may change if $ifile_root isn't module name (??)
} else {
- ($ifile_root = $ifile) =~ s/\.[^\.\/]+$//;
- ($ifile_root_file = $ifile_root) =~ s|.*/||;
+ $ifile = "$Tmp_prefix.hs"; # we know that's where we put the input
+ $ifile_root = '_stdin';
+ $ofile_target = '_stdout'; # gratuitous?
+ $hifile_target= '_stdout'; # ditto?
}
\end{code}
-We now decide what phases of the compilation system we will run over
-this file. The defaults are the ones established when processing flags.
-(That established what the last phase run for all files is.)
+We need to decide what phases of the compilation system we will run
+over this file. The defaults are the ones established when processing
+flags. (That established what the last phase run for all files is.)
-The lower-case names are the local ones (as is usual), just for this
-one file.
+We do the pre-recompilation-checker phases here; the rest later.
\begin{code}
- local($do_lit2pgm) = $Do_lit2pgm;
- local($do_hscpp) = $Do_hscpp;
- local($do_hsp) = $Do_hsp;
- local($do_hsc) = $Do_hsc;
- local($do_as) = $Do_as;
- local($do_cc) = ( $Do_cc != -1) # i.e., it was set explicitly
- ? $Do_cc
- : ( ($ProduceC) ? 1 : 0 );
\end{code}
Look at the suffix and decide what initial phases of compilation may
be dropped off for this file. Also the rather boring business of
which files are coming-in/going-out.
+
+Again, we'll do the post-recompilation-checker parts of this later.
\begin{code}
+ local($do_lit2pgm) = ($ifile =~ /\.lhs$/) ? 1 : 0;
+ local($do_hscpp) = 1; # but "hscpp" might really be "cat"
+ local($do_hsc) = 1;
+ local($do_cc) = ( $Do_cc != -1) # i.e., it was set explicitly
+ ? $Do_cc
+ : ( ($HscOut eq '-C=') ? 1 : 0 );
+ local($do_as) = $Do_as;
+
# names of the files to stuff between phases
# defaults are temporaries
local($in_lit2pgm) = $ifile;
local($lit2pgm_hscpp) = "$Tmp_prefix.lpp";
- local($hscpp_hsp) = "$Tmp_prefix.cpp";
- local($hsp_hsc) = "$Tmp_prefix.hsp";
- local($hsc_cc) = "$Tmp_prefix.hc";
-
- # to help C compilers grok .hc files [ToDo: de-hackify]
- local($cc_help) = "ghc$$.c";
- local($cc_help_s) = "ghc$$.s";
-
- local($hsc_hi) = "$Tmp_prefix$HiSuffix";
+ local($hscpp_hsc) = "$Tmp_prefix.cpp";
+ local($hsc_out) = ( $HscOut eq '-C=' ) ? "$Tmp_prefix.hc" : "$Tmp_prefix.s" ;
+ local($hsc_hi) = "$Tmp_prefix.hi";
local($cc_as_o) = "${Tmp_prefix}_o.s"; # temporary for raw .s file if opt C
- local($cc_as) = "$Tmp_prefix.s";
- local($as_out) = ($Specific_output_file ne '' && ! $Do_lnkr)
- ? $Specific_output_file
- : &odir_ify("${ifile_root}${Osuffix}");
+ local($cc_as) = "$Tmp_prefix.s"; # mangled or hsc-produced .s code
+ local($as_out) = $ofile_target;
- local($is_hc_file) = 1; #Is the C code .hc or .c
+ local($is_hc_file) = 1; #Is the C code .hc or .c? Assume .hc for now
if ($ifile =~ /\.lhs$/) {
- push(@Link_file, &odir_ify("${ifile_root}${Osuffix}"));
+ ; # nothing to change
} elsif ($ifile =~ /\.hs$/) {
$do_lit2pgm = 0;
$lit2pgm_hscpp = $ifile;
- push(@Link_file, &odir_ify("${ifile_root}${Osuffix}"));
- } elsif ($ifile =~ /\.hc$/) {
- $do_lit2pgm = 0; $do_hscpp = 0; $do_hsp = 0; $do_hsc = 0; $do_cc = 1;
- $hsc_cc = $ifile;
- push(@Link_file, &odir_ify("${ifile_root}${Osuffix}"));
+ } elsif ($ifile =~ /\.hc$/ || $ifile =~ /_hc$/ ) { # || $ifile =~ /\.$Isuffix$/o) # ToDo: better
+ $do_lit2pgm = 0; $do_hscpp = 0; $do_hsc = 0; $do_cc = 1;
+ $hsc_out = $ifile;
} elsif ($ifile =~ /\.c$/) {
- $do_lit2pgm = 0; $do_hscpp = 0; $do_hsp = 0; $do_hsc = 0; $do_cc = 1;
- $hsc_cc = $ifile; $is_hc_file = 0;
- push(@Link_file, &odir_ify("${ifile_root}${Osuffix}"));
+ $do_lit2pgm = 0; $do_hscpp = 0; $do_hsc = 0; $do_cc = 1;
+ $hsc_out = $ifile; $is_hc_file = 0;
} elsif ($ifile =~ /\.s$/) {
- $do_lit2pgm = 0; $do_hscpp = 0; $do_hsp = 0; $do_hsc = 0; $do_cc = 0;
+ $do_lit2pgm = 0; $do_hscpp = 0; $do_hsc = 0; $do_cc = 0;
$cc_as = $ifile;
- push(@Link_file, &odir_ify("${ifile_root}${Osuffix}"));
- } else {
- if ($ifile !~ /\.a$/) {
- print STDERR "$Pgm: don't recognise suffix on `$ifile'; passing it through to linker\n";
- }
- $do_lit2pgm = 0; $do_hscpp = 0; $do_hsp = 0; $do_hsc = 0; $do_cc = 0; $do_as = 0;
- push(@Link_file, $ifile);
+ } else { # don't know what it is, but nothing to do herein...
+ $do_lit2pgm = 0; $do_hscpp = 0; $do_hsc = 0; $do_cc = 0; $do_as = 0;
}
+
+ # OK, have a bash on the first two phases:
+ &runLit2pgm($in_lit2pgm, $lit2pgm_hscpp)
+ if $do_lit2pgm;
+
+ &runHscpp($in_lit2pgm, $lit2pgm_hscpp, $hscpp_hsc)
+ if $do_hscpp;
\end{code}
+We now think about whether to run hsc/cc or not (when hsc produces .s
+stuff, it effectively takes the place of both phases).
+
To get the output file name right: for each phase that we are {\em
-not} going to run, set its input (i.e., the output of its preceding phase) to
-@"$ifile_root.<suffix>"@.
+not} going to run, set its input (i.e., the output of its preceding
+phase) to @"$ifile_root.<suffix>"@.
\begin{code}
- # lit2pgm -- no preceding phase
- if (! $do_hscpp) {
- $lit2pgm_hscpp = "$ifile_root.lpp????"; # not done
- }
- if (! $do_hsp) {
- $hscpp_hsp = "$ifile_root.cpp????"; # not done
- }
- if (! $do_hsc) {
- $hsp_hsc = "$ifile_root.hsp????"; # not done
- }
- if (! $do_cc) {
- $hsc_cc = &odir_ify("$ifile_root.hc");
- }
- if (! $do_as) {
- if ($Specific_output_file ne '') {
- $cc_as = $Specific_output_file;
- } else {
- $cc_as = &odir_ify(( $Only_preprocess_C ) ? "$ifile_root.i" : "$ifile_root.s");
- }
- }
-\end{code}
+ local($going_interactive) = $HscOut eq '-N=' || $ifile_root eq '_stdin';
-OK, now do it! Note that we don't come back from a @run_something@ if
-it fails.
-\begin{code}
- if ($do_lit2pgm) {
- local($to_do) = "echo '#line 1 \"$in_lit2pgm\"' > $lit2pgm_hscpp; ".
- "$Unlit @Unlit_flags $in_lit2pgm - >> $lit2pgm_hscpp";
- @Files_to_tidy = ( $lit2pgm_hscpp );
- &run_something($to_do, 'literate pre-processor');
- }
- if ($do_hscpp) {
- # ToDo: specific output?
- if ($HsCpp eq $Cat) {
- local($to_do) = "echo '#line 1 \"$in_lit2pgm\"' > $hscpp_hsp; ".
- "$HsCpp $lit2pgm_hscpp >> $hscpp_hsp";
- @Files_to_tidy = ( $hscpp_hsp );
- &run_something($to_do, 'Ineffective C pre-processor');
- } else {
- local($includes) = '-I' . join(' -I',@Include_dir);
- local($to_do) = "echo '#line 1 \"$in_lit2pgm\"' > $hscpp_hsp; ".
- "$HsCpp $Verbose @HsCpp_flags -D__HASKELL1__=$haskell1_version -D__GLASGOW_HASKELL__=$ghc_version_info $includes $lit2pgm_hscpp >> $hscpp_hsp";
- @Files_to_tidy = ( $hscpp_hsp );
- &run_something($to_do, 'Haskellised C pre-processor');
- }
- }
- if ($do_hsp) {
- # glue imports onto HsP_flags
- # if new parser, then put a comma on the front of all of them.
- local($hsprefix) = ($do_hsp == 2) ? ',' : '';
-
- foreach $a ( @HsP_flags ) { $a = "$hsprefix$a" unless $a =~ /^,/; }
- foreach $dir ( @Import_dir ) { push(@HsP_flags, "$hsprefix-I$dir"); }
- foreach $dir ( @SysImport_dir ) { push(@HsP_flags, "$hsprefix-J$dir"); }
+ if (! $do_cc && ! $do_as) { # stopping after hsc
+ $hsc_out = ($Specific_output_file ne '')
+ ? $Specific_output_file
+ : &odir_ify($ifile_root, ($HscOut eq '-C=') ? 'hc' : 's');
+
+ $ofile_target = $hsc_out; # reset
}
- if ($do_hsp == 1) { # "old" parser
- local($to_do) = "$HsP $Verbose @HsP_flags $hscpp_hsp > $hsp_hsc";
- @Files_to_tidy = ( $hsp_hsc );
- &run_something($to_do, 'Haskell parser');
- if ($Dump_parser_output) {
- print STDERR `$Cat $hsp_hsc`;
- }
- @HsP_flags = (); # reset!
+ if (! $do_as) { # stopping after gcc (or hsc)
+ $cc_as = ($Specific_output_file ne '')
+ ? $Specific_output_file
+ : &odir_ify($ifile_root, ( $Only_preprocess_C ) ? 'i' : 's');
+
+ $ofile_target = $cc_as; # reset
}
- if ($do_hsc) {
- # here, we may produce .hc and/or .hi files
- local($output) = '';
- local($c_source) = "$ifile_root.hc";
- local($c_output) = $hsc_cc; # defaults
- local($s_output) = $cc_as;
- local($hi_output) = "$ifile_root$HiSuffix";
- local($going_interactive) = 0;
-
- if ($Specific_output_file ne '' && ! $do_cc) {
- $c_source = $c_output = $Specific_output_file;
- @Files_to_tidy = ( $Specific_output_file ) if $Specific_output_file ne '-';
- }
- if ($Specific_hi_file ne '') {
- # we change the suffix (-hisuf) even if a specific -ohi file:
- $Specific_hi_file =~ s/\.hi$/$HiSuffix/;
- $hi_output = $Specific_hi_file;
- @Files_to_tidy = ( $Specific_hi_file ) if $Specific_hi_file ne '-';
- }
- if ( ! ($ProduceC || $ProduceS)
- || $ifile_root eq '_stdin' # going interactive...
- || ($c_output eq '-' && $hi_output eq '-')) {
- $going_interactive = 1;
-#OLD: $output = '1>&2'; # interactive/debugging, to stderr
- @Files_to_tidy = ();
- # don't need .hi (unless magic value "2" says we wanted it anyway):
- if ( $ProduceHi == 2 ) {
- $output .= " -hi$hsc_hi";
- unlink($hsc_hi); # needs to be cleared; will be appended to
- } else {
- $ProduceHi = 0;
- }
- $do_cc = 0; $do_as = 0; $Do_lnkr = 0; # and we won't go any further...
- }
+\end{code}
- if ( ! $going_interactive ) {
- if ( $ProduceHi ) {
- # we always go to a temp file for these (for later diff'ing)
- $output = "-hi$hsc_hi";
- unlink($hsc_hi); # needs to be cleared; will be appended to
- @Files_to_tidy = ( $hsc_hi );
- }
- if ( $ProduceC ) {
- $output .= " -C$c_output";
- push(@Files_to_tidy, $c_output);
-
- open(CFILE, "> $c_output") || &tidy_up_and_die(1,"$Pgm: failed to open `$c_output' (to write)\n");
- print CFILE "#line 2 \"$c_source\"\n";
- close(CFILE) || &tidy_up_and_die(1,"Failed writing to $c_output\n");
- # the "real" C output will then be appended
- }
- if ( $ProduceS ) {
- $output .= " -fasm-$ProduceS -S$s_output";
- push(@Files_to_tidy, $s_output);
-
- # ToDo: ummm,... this isn't doing anything (WDP 94/11)
- open(SFILE, "> $s_output") || &tidy_up_and_die(1,"$Pgm: failed to open `$s_output' (to write)\n");
- close(SFILE) || &tidy_up_and_die(1,"Failed writing to $s_output\n");
- # the "real" assembler output will then be appended
- }
- }
+Check if hsc needs to be run at all.
- # if we're compiling foo.hs, we want the GC stats to end up in foo.stat
- if ( $CollectingGCstats ) {
- if ($RTS_style eq 'hbc') {
- push(@HsC_rts_flags, '-S'); # puts it in "STAT"
- } else {
- push(@HsC_rts_flags, "-S$ifile_root.stat");
- push(@Files_to_tidy, "$ifile_root.stat");
- }
- }
+\begin{code}
+ local($more_processing_required) = 1;
- if ( $CollectGhcTimings ) { # assume $RTS_style eq 'ghc'
- # emit nofibbish time/bytes-alloc stats to stderr;
- # see later .stat file post-processing
- push(@HsC_rts_flags, "-s$Tmp_prefix.stat");
- push(@Files_to_tidy, "$Tmp_prefix.stat");
- }
+ if ( $Do_recomp_chkr && $do_hsc && ! $going_interactive ) {
+ # recompilation-checking is important enough to live off by itself
+ require('ghc-recomp.prl')
+ || &tidy_up_and_die(1,"$Pgm: panic: can't load ghc-recomp.prl!\n");
- local($dump);
- if ($Specific_dump_file ne '') {
- $dump = "2>> $Specific_dump_file";
- $Using_dump_file = 1;
- } else {
- $dump = '';
- }
-
- local($to_do);
- if ($RTS_style eq 'hbc') {
- # NB: no parser flags
- $to_do = "$HsC < $hsp_hsc $dump @HsC_rts_flags - @HsC_flags $CoreLint $Verbose $output";
- } elsif ($do_hsp == 1) { # old style parser -- no HsP_flags
- $to_do = "$HsC < $hsp_hsc $dump @HsC_flags $CoreLint $Verbose $output +RTS @HsC_rts_flags";
- } else { # new style
- $to_do = "$HsC ,-H @HsP_flags ,$hscpp_hsp $dump @HsC_flags $CoreLint $Verbose $output +RTS @HsC_rts_flags";
- }
- &run_something($to_do, 'Haskell compiler');
+ $more_processing_required
+ = &runRecompChkr($ifile, $hscpp_hsc, $ifile_root, $ofile_target, $hifile_target);
- # compensate further for HBC's -S rts opt:
- if ($CollectingGCstats && $RTS_style eq 'hbc') {
- unlink("$ifile_root.stat");
- rename('STAT', "$ifile_root.stat");
+ if ( ! $more_processing_required ) {
+ print STDERR "$Pgm:recompile: NOT NEEDED!\n"; # Yay!
+ # propagate dependency:
+ &run_something("touch $ofile_target", "Touch $ofile_target, to propagate dependencies");
}
+ }
- # finish business w/ nofibbish time/bytes-alloc stats
- &process_ghc_timings() if $CollectGhcTimings;
+ $do_hsc = 0, $do_cc = 0, $do_as = 0 if ! $more_processing_required;
+\end{code}
- # if non-interactive, heave in the consistency info at the end
- # NB: pretty hackish (depends on how $output is set)
- if ( ! $going_interactive ) {
- if ( $ProduceC ) {
- $to_do = "echo 'static char ghc_hsc_ID[] = \"\@(#)hsc $ifile\t$HsC_major_version.$HsC_minor_version,$HsC_consist_options\";' >> $c_output";
- }
- if ( $ProduceS ) {
- local($consist) = "hsc.$ifile.$HsC_major_version.$HsC_minor_version.$HsC_consist_options";
- $consist =~ s/,/./g;
- $consist =~ s/\//./g;
- $consist =~ s/-/_/g;
- $consist =~ s/[^A-Za-z0-9_.]/ZZ/g; # ToDo: properly?
- $to_do = "echo '\n\t.text\n$consist:' >> $s_output";
- }
- &run_something($to_do, 'Pin on Haskell consistency info');
- }
+\begin{code}
+ if ( $do_hsc ) {
+
+ &runHsc($ifile_root, $hsc_out, $hsc_hi, $going_interactive);
- # call the special mangler to produce the .hi/.h(h?) files...
- &diff_hi_file($hsc_hi, $hi_output)
- if $ProduceHi == 1 && ! $going_interactive;
-#OLD: &extract_c_and_hi_files("$Tmp_prefix.hsc", $c_output, $hi_output, $c_source)
+ # interface-handling is important enough to live off by itself
+ require('ghc-iface.prl')
+ || &tidy_up_and_die(1,"$Pgm: panic: can't load ghc-iface.prl!\n");
- # if we produced an interface file "no matter what",
- # print what we got on stderr (ToDo: honor -ohi flag)
- if ( $ProduceHi == 2 ) {
- print STDERR `$Cat $hsc_hi`;
- }
+ &postprocessHiFile($hsc_hi, $hifile_target, $going_interactive);
# save a copy of the .hc file, even if we are carrying on...
- if ($ProduceC && $do_cc && $Keep_hc_file_too) {
- local($to_do) = "$(RM) $ifile_root.hc; cp $c_output $ifile_root.hc";
+ if ($HscOut eq '-C=' && $do_cc && $Keep_hc_file_too) {
+ local($to_do) = "$Rm $ifile_root.hc; $Cp $hsc_out $ifile_root.hc";
&run_something($to_do, 'Saving copy of .hc file');
}
# save a copy of the .s file, even if we are carrying on...
- if ($ProduceS && $do_as && $Keep_s_file_too) {
- local($to_do) = "$(RM) $ifile_root.s; cp $cc_as $ifile_root.s";
+ if ($HscOut eq '-S=' && $do_as && $Keep_s_file_too) {
+ local($to_do) = "$Rm $ifile_root.s; $Cp $hsc_out $ifile_root.s";
&run_something($to_do, 'Saving copy of .s file');
}
# if we're going to split up object files,
# we inject split markers into the .hc file now
- if ( $ProduceC && $SplitObjFiles ) {
- &inject_split_markers ( $c_output );
+ if ( $HscOut eq '-C=' && $SplitObjFiles ) {
+ &inject_split_markers ( $hsc_out );
}
}
+
if ($do_cc) {
+ &runGcc ($is_hc_file, $hsc_out, $cc_as_o);
+ &runMangler($is_hc_file, $cc_as_o, $cc_as, $ifile_root);
+ }
+
+ &split_asm_file($cc_as) if $do_as && $SplitObjFiles;
+
+ &runAs($as_out, $ifile_root) if $do_as;
+\end{code}
+
+Finally, decide what to queue up for linker input.
+\begin{code}
+ # tentatively assume we will eventually produce linker input:
+ push(@Link_file, &odir_ify($ifile_root, 'o'));
+
+#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$/;
+
+ # oops; we tentatively pushed the wrong thing; fix & do the right thing
+ pop(@Link_file); push(@Link_file, $ifile);
+ }
+
+} # end of ProcessInputFile
+\end{code}
+
+%************************************************************************
+%* *
+\section[Driver-run-phases]{Routines to run the various phases}
+%* *
+%************************************************************************
+
+\begin{code}
+sub runLit2pgm {
+ local($in_lit2pgm, $lit2pgm_hscpp) = @_;
+
+ local($to_do) = "echo '#line 1 \"$in_lit2pgm\"' > $lit2pgm_hscpp && ".
+ "$Unlit @Unlit_flags $in_lit2pgm - >> $lit2pgm_hscpp";
+ @Files_to_tidy = ( $lit2pgm_hscpp );
+
+ &run_something($to_do, 'literate pre-processor');
+}
+\end{code}
+
+\begin{code}
+sub runHscpp {
+ local($in_lit2pgm, $lit2pgm_hscpp, $hscpp_hsc) = @_;
+
+ local($to_do);
+
+ if ($HsCpp eq $Cat) {
+ $to_do = "echo '#line 1 \"$in_lit2pgm\"' > $hscpp_hsc && ".
+ "$HsCpp $lit2pgm_hscpp >> $hscpp_hsc";
+ @Files_to_tidy = ( $hscpp_hsc );
+ &run_something($to_do, 'Ineffective C pre-processor');
+ } else {
local($includes) = '-I' . join(' -I',@Include_dir);
- local($cc);
- local($s_output);
- local($c_flags) = "@CcBoth_flags";
- local($ddebug_flag) = ( $DEBUGging ) ? '-DDEBUG' : '';
- if ($RegisteriseC) {
- $cc = $CcRegd;
- $s_output = ($is_hc_file || $TargetPlatform =~ /^hppa/) ? $cc_as_o : $cc_as;
- $c_flags .= " @CcRegd_flags";
- $c_flags .= ($is_hc_file) ? " @CcRegd_flags_hc" : " @CcRegd_flags_c";
- } else {
- $cc = $CcUnregd;
- $s_output = $cc_as;
- $c_flags .= " @CcUnregd_flags";
- $c_flags .= ($is_hc_file) ? " @CcUnregd_flags_hc" : " @CcUnregd_flags_c";
- }
-
- # C compiler won't like the .hc extension. So we create
- # a tmp .c file which #include's the needful.
- open(TMP, "> $cc_help") || &tidy_up_and_die(1,"$Pgm: failed to open `$cc_help' (to write)\n");
- if ( $is_hc_file ) {
- print TMP <<EOINCL;
-#ifdef __STG_GCC_REGS__
-# if ! (defined(MAIN_REG_MAP) || defined(MARK_REG_MAP) || defined(SCAN_REG_MAP) || defined(SCAV_REG_MAP) || defined(FLUSH_REG_MAP))
-# define MAIN_REG_MAP
-# endif
-#endif
-#include "stgdefs.h"
-EOINCL
- # user may have asked for #includes to be injected...
- print TMP @CcInjects if $#CcInjects >= 0;
- }
- # heave in the consistency info
- print TMP "static char ghc_cc_ID[] = \"\@(#)cc $ifile\t$Cc_major_version.$Cc_minor_version,$Cc_consist_options\";\n";
+ $to_do = "echo '#line 1 \"$in_lit2pgm\"' > $hscpp_hsc && ".
+ "$HsCpp $Verbose $genSPECS_flag @HsCpp_flags -D__HASKELL1__=$Haskell1Version -D__GLASGOW_HASKELL__=$GhcVersionInfo $includes $lit2pgm_hscpp >> $hscpp_hsc";
+ @Files_to_tidy = ( $hscpp_hsc );
+ &run_something($to_do, 'Haskellised C pre-processor');
+ }
+}
+\end{code}
- # and #include the real source
- print TMP "#include \"$hsc_cc\"\n";
- close(TMP) || &tidy_up_and_die(1,"Failed writing to $cc_help\n");
+\begin{code}
+sub runHsc {
+ local($ifile_root, $hsc_out, $hsc_hi, $going_interactive) = @_;
- local($to_do) = "$cc $Verbose $ddebug_flag $c_flags @Cpp_define -D__HASKELL1__=$haskell1_version $includes $cc_help > $Tmp_prefix.ccout 2>&1 && ( if [ $cc_help_s != $s_output ] ; then mv $cc_help_s $s_output ; else exit 0 ; fi )";
- # note: __GLASGOW_HASKELL__ is pointedly *not* #defined at the C level.
- if ( $Only_preprocess_C ) { # HACK ALERT!
- $to_do =~ s/ -S\b//g;
- }
- @Files_to_tidy = ( $cc_help, $cc_help_s, $s_output );
- $PostprocessCcOutput = 1; # hack, dear hack...
- &run_something($to_do, 'C compiler');
- $PostprocessCcOutput = 0;
- unlink($cc_help, $cc_help_s);
-
- if ( ($RegisteriseC && $is_hc_file)
- || $Dump_asm_insn_counts
- || $Dump_asm_globals_info ) {
- # dynamically load assembler-fiddling code, which we are about to use
- local($target) = '';
- $target = 'alpha' if $TargetPlatform =~ /^alpha-/;
- $target = 'hppa' if $TargetPlatform =~ /^hppa/;
- $target = 'iX86' if $TargetPlatform =~ /^i[34]86-/;
- $target = 'm68k' if $TargetPlatform =~ /^m68k-/;
- $target = 'mips' if $TargetPlatform =~ /^mips-/;
- $target = 'solaris' if $TargetPlatform =~ /^sparc-sun-solaris2/;
- $target = 'sparc' if $TargetPlatform =~ /^sparc-sun-sunos4/;
- $target ne ''
- || &tidy_up_and_die(1,"$Pgm: panic: can't decipher $TargetPlatform!\n");
- require("ghc-asm-$target.prl")
- || &tidy_up_and_die(1,"$Pgm: panic: can't load ghc-asm-$target.prl!\n");
- }
-
- if ( $Dump_raw_asm ) { # to stderr, before mangling
- local($to_pr) = ($RegisteriseC) ? $cc_as_o : $cc_as ;
- print STDERR `cat $to_pr`;
- }
+ # prepend comma to HsP flags (so hsc can tell them apart...)
+ foreach $a ( @HsP_flags ) { $a = ",$a" unless $a =~ /^,/; }
- if ($RegisteriseC) {
- if ($is_hc_file) {
- # post-process the assembler [.hc files only]
- &mangle_asm($cc_as_o, $cc_as);
- } elsif ($TargetPlatform =~ /^hppa/) {
- # minor mangling of non-threaded files for hp-pa only
- require("ghc-asm-hppa.prl")
- || &tidy_up_and_die(1,"$Pgm: panic: can't load ghc-asm-hppa.prl!\n");
- &mini_mangle_asm($cc_as_o, $cc_as);
- }
- }
+ &makeHiMap() unless $HiMapDone;
+ push(@HsC_flags, "-himap=$HiMapFile");
- # collect interesting (static-use) info
- &dump_asm_insn_counts($cc_as) if $Dump_asm_insn_counts;
- &dump_asm_globals_info($cc_as) if $Dump_asm_globals_info;
+ # here, we may produce .hc/.s and/or .hi files
+ local($output) = '';
+ @Files_to_tidy = ();
- # 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 ( $going_interactive ) {
+ # don't need .hi unless going to show it on stdout:
+ $ProduceHi = '-nohifile=' if ! $HiOnStdout;
+ $do_cc = 0; $do_as = 0; $Do_lnkr = 0; # and we won't go any further...
}
- if ($do_as) {
- # if we're splitting .o files...
- if ( $SplitObjFiles ) {
- &split_asm_file ( $cc_as );
- }
+ # 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 );
- local($asmblr) = ( $As ) ? $As : ($RegisteriseC ? $CcRegd : $CcUnregd );
+ # if we're compiling foo.hs, we want the GC stats to end up in foo.stat
+ if ( $CollectingGCstats ) {
+ push(@HsC_rts_flags, "-S$ifile_root.stat");
+ push(@Files_to_tidy, "$ifile_root.stat");
+ }
- if ( ! $SplitObjFiles ) {
- local($to_do) = "$asmblr -o $as_out -c @As_flags $cc_as";
- @Files_to_tidy = ( $as_out );
- &run_something($to_do, 'Unix assembler');
+ if ( $CollectGhcTimings ) { # assume $RTS_style eq 'ghc'
+ # emit nofibbish time/bytes-alloc stats to stderr;
+ # see later .stat file post-processing
+ push(@HsC_rts_flags, "-s$Tmp_prefix.stat");
+ push(@Files_to_tidy, "$Tmp_prefix.stat");
+ }
- } else { # more complicated split-ification...
+ local($dump) = '';
+ if ($Specific_dump_file ne '') {
+ $dump = "2>> $Specific_dump_file";
+ $Using_dump_file = 1;
+ }
- # must assemble files $Tmp_prefix__[1 .. $NoOfSplitFiles].s
+ local($to_do);
+ $to_do = "$HsC @HsP_flags ,$hscpp_hsc $dump @HsC_flags $CoreLint $Verbose $output +RTS @HsC_rts_flags";
+ &run_something($to_do, 'Haskell compiler');
+
+ # finish business w/ nofibbish time/bytes-alloc stats
+ &process_ghc_timings() if $CollectGhcTimings;
+
+ # if non-interactive, heave in the consistency info at the end
+ # NB: pretty hackish (depends on how $output is set)
+ if ( ! $going_interactive ) {
+ if ( $HscOut eq '-C=' ) {
+ $to_do = "echo 'static char ghc_hsc_ID[] = \"\@(#)hsc $ifile\t$HsC_major_version.$HsC_minor_version,$HsC_consist_options\";' >> $hsc_out";
+
+ } elsif ( $HscOut eq '-S=' ) {
+ local($consist) = "hsc.$ifile.$HsC_major_version.$HsC_minor_version.$HsC_consist_options";
+ $consist =~ s/,/./g;
+ $consist =~ s/\//./g;
+ $consist =~ s/-/_/g;
+ $consist =~ s/[^A-Za-z0-9_.]/ZZ/g; # ToDo: properly?
+ $to_do = "echo '\n\t.text\n$consist:' >> $hsc_out";
+ }
+ &run_something($to_do, 'Pin on Haskell consistency info');
+ }
+}
+\end{code}
- for ($f = 1; $f <= $NoOfSplitFiles; $f++ ) {
- local($split_out) = &odir_ify("${ifile_root}__${f}${Osuffix}");
- local($to_do) = "$asmblr -o $split_out -c @As_flags ${Tmp_prefix}__${f}.s";
- @Files_to_tidy = ( $split_out );
+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 = '';
- &run_something($to_do, 'Unix assembler');
+sub makeHiMap {
+
+ # collect in %HiMap; write later; also used elsewhere in driver
+
+ local($mod, $path, $d, $e);
+
+ foreach $d ( @Import_dir ) {
+ opendir(DIR, $d) || &tidy_up_and_die(1,"$Pgm: error when reading directory: $d\n");
+ local(@entry) = readdir(DIR);
+ foreach $e ( @entry ) {
+ next unless $e =~ /([A-Z][A-Za-z0-9_]*)\.$HiSuffix$/o;
+ $mod = $1;
+ $path = "$d/$e";
+ $path =~ s,^\./,,;
+
+ if ( ! defined($HiMap{$mod}) ) {
+ $HiMap{$mod} = $path;
+ } else {
+ &already_mapped_err($mod, $HiMap{$mod}, $path);
}
}
+ closedir(DIR); # || &tidy_up_and_die(1,"$Pgm: error when closing directory: $d\n");
}
-} # end of ProcessInputFile
+
+ foreach $d ( @SysImport_dir ) {
+ opendir(DIR, $d) || &tidy_up_and_die(1,"$Pgm: error when reading directory: $d\n");
+ local(@entry) = readdir(DIR);
+ foreach $e ( @entry ) {
+ next unless $e =~ /([A-Z][A-Za-z0-9_]*)\.$SysHiSuffix$/o;
+ next if $NoImplicitPrelude && $e =~ /Prelude\.$SysHiSuffix$/o;
+
+ $mod = $1;
+ $path = "$d/$e";
+ $path =~ s,^\./,,;
+
+ if ( ! defined($HiMap{$mod}) ) {
+ $HiMap{$mod} = $path;
+ } elsif ( $mod ne 'Main' ) { # saves useless warnings...
+ &already_mapped_err($mod, $HiMap{$mod}, $path);
+ }
+ }
+ closedir(DIR); # || &tidy_up_and_die(1,"$Pgm: error when closing directory: $d\n");
+ }
+
+ $HiMapFile = "$Tmp_prefix.himap";
+ unlink($HiMapFile);
+ open(HIMAP, "> $HiMapFile") || &tidy_up_and_die(1,"$Pgm: can't open $HiMapFile\n");
+ foreach $d (keys %HiMap) {
+ print HIMAP $d, ' ', $HiMap{$d}, "\n";
+ }
+ close(HIMAP) || &tidy_up_and_die(1,"$Pgm: error when closing $HiMapFile\n");
+
+ $HiMapDone = 1;
+}
+
+sub already_mapped_err {
+ local($mod, $mapped_to, $path) = @_;
+
+ # OK, it isn't really an error if $mapped_to and $path turn
+ # out to be the same thing.
+ ($m_dev,$m_ino,$m_mode,$m_nlink,$m_uid,$m_gid,$m_rdev,$m_size,
+ $m_atime,$m_mtime,$m_ctime,$m_blksize,$m_blocks) = stat($mapped_to);
+ ($p_dev,$p_ino,$p_mode,$p_nlink,$p_uid,$p_gid,$p_rdev,$p_size,
+ $p_atime,$p_mtime,$p_ctime,$p_blksize,$p_blocks) = stat($path);
+
+ return if $m_ino == $p_ino; # same inode number
+
+ print STDERR "$Pgm: module $mod already mapped to $mapped_to";
+ print STDERR ";\n\tignoring: $path\n";
+}
\end{code}
%************************************************************************
%************************************************************************
\begin{code}
+sub osuf_ify {
+ local($ofile,$def_suffix) = @_;
+
+ return(($Osuffix eq '') ? "$ofile.$def_suffix" : "$ofile.$Osuffix" );
+}
+
sub odir_ify {
- local($orig_file) = @_;
+ local($orig_file, $def_suffix) = @_;
if ($Specific_output_dir eq '') { # do nothing
- return($orig_file);
+ &osuf_ify($orig_file, $def_suffix);
} else {
local ($orig_file_only);
($orig_file_only = $orig_file) =~ s|.*/||;
- return("$Specific_output_dir/$orig_file_only");
+ &osuf_ify("$Specific_output_dir/$orig_file_only",$def_suffix);
+ }
+}
+\end{code}
+
+\begin{code}
+sub runGcc {
+ local($is_hc_file, $hsc_out, $cc_as_o) = @_;
+
+ local($includes) = '-I' . join(' -I', @Include_dir);
+ local($cc);
+ local($s_output);
+ local($c_flags) = "@CcBoth_flags";
+ local($ddebug_flag) = ( $DEBUGging ) ? '-DDEBUG' : '';
+
+ # "input" files to use that are not in some weird directory;
+ # to help C compilers grok .hc files [ToDo: de-hackify]
+ local($cc_help) = "ghc$$.c";
+ local($cc_help_s) = "ghc$$.s";
+
+ $cc = $CcRegd;
+ $s_output = ($is_hc_file || $TargetPlatform =~ /^(hppa|i386)/) ? $cc_as_o : $cc_as;
+ $c_flags .= " @CcRegd_flags";
+ $c_flags .= ($is_hc_file) ? " @CcRegd_flags_hc" : " @CcRegd_flags_c";
+
+ # C compiler won't like the .hc extension. So we create
+ # a tmp .c file which #include's the needful.
+ open(TMP, "> $cc_help") || &tidy_up_and_die(1,"$Pgm: failed to open `$cc_help' (to write)\n");
+ if ( $is_hc_file ) {
+ print TMP <<EOINCL;
+#ifdef __STG_GCC_REGS__
+# if ! (defined(MAIN_REG_MAP) || defined(MARK_REG_MAP) || defined(SCAN_REG_MAP) || defined(SCAV_REG_MAP) || defined(FLUSH_REG_MAP))
+# define MAIN_REG_MAP
+# endif
+#endif
+#include "stgdefs.h"
+EOINCL
+ # user may have asked for #includes to be injected...
+ print TMP @CcInjects if $#CcInjects >= 0;
+ }
+ # heave in the consistency info
+ print TMP "static char ghc_cc_ID[] = \"\@(#)cc $ifile\t$Cc_major_version.$Cc_minor_version,$Cc_consist_options\";\n";
+
+ # and #include the real source
+ print TMP "#include \"$hsc_out\"\n";
+ close(TMP) || &tidy_up_and_die(1,"Failed writing to $cc_help\n");
+
+ local($to_do) = "$cc $Verbose $ddebug_flag $c_flags @Cpp_define -D__HASKELL1__=$Haskell1Version $includes $cc_help > $Tmp_prefix.ccout 2>&1 && ( if [ $cc_help_s != $s_output ] ; then mv $cc_help_s $s_output ; else exit 0 ; fi )";
+ # note: __GLASGOW_HASKELL__ is pointedly *not* #defined at the C level.
+ if ( $Only_preprocess_C ) { # HACK ALERT!
+ $to_do =~ s/ -S\b//g;
+ }
+ @Files_to_tidy = ( $cc_help, $cc_help_s, $s_output );
+ $PostprocessCcOutput = 1; # hack, dear hack...
+ &run_something($to_do, 'C compiler');
+ $PostprocessCcOutput = 0;
+ unlink($cc_help, $cc_help_s);
+}
+\end{code}
+
+\begin{code}
+sub runMangler {
+ local($is_hc_file, $cc_as_o, $cc_as, $ifile_root) = @_;
+
+ if ( $is_hc_file ) {
+ # dynamically load assembler-fiddling code, which we are about to use:
+ require('ghc-asm.prl')
+ || &tidy_up_and_die(1,"$Pgm: panic: can't load ghc-asm.prl!\n");
+ }
+
+ print STDERR `cat $cc_as_o` if $Dump_raw_asm; # to stderr, before mangling
+
+ if ($is_hc_file) {
+ # post-process the assembler [.hc files only]
+ &mangle_asm($cc_as_o, $cc_as);
+
+#OLD: for sanity:
+#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
+ require('ghc-asm.prl')
+ || &tidy_up_and_die(1,"$Pgm: panic: can't load ghc-asm.prl!\n");
+ &mini_mangle_asm_i386($cc_as_o, $cc_as);
+ }
+
+ # save a copy of the .s file, even if we are carrying on...
+ if ($do_as && $Keep_s_file_too) {
+ local($to_do) = "$Rm $ifile_root.s; $Cp $cc_as $ifile_root.s";
+ &run_something($to_do, 'Saving copy of .s file');
+ }
+}
+\end{code}
+
+\begin{code}
+sub runAs {
+ local($as_out, $ifile_root) = @_;
+
+ local($asmblr) = ( $As ) ? $As : $CcRegd;
+
+ if ( ! $SplitObjFiles ) {
+ local($to_do) = "$asmblr -o $as_out -c @As_flags $cc_as";
+ @Files_to_tidy = ( $as_out );
+ &run_something($to_do, 'Unix assembler');
+
+ } else { # more complicated split-ification...
+
+ # must assemble files $Tmp_prefix__[1 .. $NoOfSplitFiles].s
+
+ for ($f = 1; $f <= $NoOfSplitFiles; $f++ ) {
+ local($split_out) = &odir_ify("${ifile_root}__${f}",'o');
+ local($to_do) = "$asmblr -o $split_out -c @As_flags ${Tmp_prefix}__${f}.s";
+ @Files_to_tidy = ( $split_out );
+
+ &run_something($to_do, 'Unix assembler');
+ }
}
}
\end{code}
while ( <CCOUT> ) {
next if /attribute directive ignored/;
next if /call-clobbered/;
- next if /In file included .*stgdefs/;
- next if /from .*rtsdefs.h:/;
+ next if /from .*COptRegs\.lh/;
+ next if /from .*(stg|rts)defs\.h:/;
next if /from ghc\d+.c:\d+:/;
next if /from .*\.lc/;
- next if /from .*SMinternal\.lh/;
+ 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/;
%************************************************************************
%* *
-\subsection[Driver-demangle-C-and-hi]{@extract_c_and_hi_files@: Unscramble Haskell-compiler output}
-%* *
-%************************************************************************
-
-Update interface if the tmp one is newer...
-We first have to fish the module name out of the interface.
-\begin{code}
-sub diff_hi_file {
- local($tmp_hi_file, $hi_file) = @_;
- local($if_modulename) = '';
-
- # extract the module name
-
- open(TMP, "< $tmp_hi_file")|| &tidy_up_and_die(1,"$Pgm: failed to open `$tmp_hi_file' (to read)\n");
- while (<TMP>) {
- if ( /^interface ([A-Za-z0-9'_]+) / ) {
- $if_modulename = $1;
- }
- }
- close(TMP) || &tidy_up_and_die(1,"Failed reading from $tmp_hi_file\n");
- &tidy_up_and_die(1,"No module name in $tmp_hi_file\n")
- if ! $if_modulename;
-
- #compare/diff with old one
-
- if ($hi_file eq '-') {
- &run_something("cat $tmp_hi_file", "copy interface to stdout");
-
- } else {
- if ($Specific_hi_file eq '' && $if_modulename ne '') {
- if ( $hi_file =~ /\// ) {
- $hi_file =~ s/\/[^\/]+$//;
- $hi_file .= "/$if_modulename$HiSuffix";
- } else {
- $hi_file = "$if_modulename$HiSuffix";
- }
- print STDERR "interface really going into: $hi_file\n" if $Verbose;
- }
-
- if ($HiDiff_flag && -f $hi_file) {
- local($diffcmd) = '$(CONTEXT_DIFF)';
-
- &run_something("cmp -s $tmp_hi_file $hi_file || $(CONTEXT_DIFF) $hi_file $tmp_hi_file 1>&2 || exit 0",
- "Diff'ing old and new $HiSuffix files"); # NB: to stderr
- }
-
- &run_something("cmp -s $tmp_hi_file $hi_file || ( $(RM) $hi_file && $(CP) $tmp_hi_file $hi_file )",
- "Comparing old and new $HiSuffix files");
- }
-}
-\end{code}
-
-%************************************************************************
-%* *
\subsection[Driver-ghctiming]{Emit nofibbish GHC timings}
%* *
%************************************************************************
local($SysSpecificTiming) = 'ghc';
open(STATS, $StatsFile) || die "Failed when opening $StatsFile\n";
+ local($tot_live) = 0; # for calculating avg residency
+
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 ( /^\s*([0-9,]+) bytes maximum residency .* (\d+) sample/ ) {
}
}
close(STATS) || die "Failed when closing $StatsFile\n";
+ if ( defined($ResidencySamples) && $ResidencySamples > 0 ) {
+ $AvgResidency = int ($tot_live / $ResidencySamples) ;
+ }
# warn about what we didn't find
print STDERR "Warning: BytesAlloc not found in stats file\n" unless defined($BytesAlloc);
# things we didn't necessarily expect to find
$MaxResidency = 0 unless defined($MaxResidency);
+ $AvgResidency = 0 unless defined($AvgResidency);
$ResidencySamples = 0 unless defined($ResidencySamples);
# a bit of tidying
# print out what we found
print STDERR "<<$SysSpecificTiming: ",
- "$BytesAlloc bytes, $GCs GCs, $MaxResidency 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), $InitTime INIT ($InitElapsed elapsed), $MutTime MUT ($MutElapsed elapsed), $GcTime GC ($GcElapsed elapsed)",
" :$SysSpecificTiming>>\n";
# OK, party over
\begin{code}
sub tidy_up {
- local($to_do) = "\n$(RM) $Tmp_prefix*";
+ local($to_do) = "\n$Rm $Tmp_prefix*";
if ( $Tmp_prefix !~ /^\s*$/ ) {
print STDERR "$to_do\n" if $Verbose;
system($to_do);
Note: no error-checking; \tr{-Rmax-heapsize -Rgc-stats} will silently
gobble the second argument (and probably set the heapsize to something
-nonsensical). (ToDo?)
+nonsensical).
\begin{code}
sub grab_arg_arg {
local($option, $rest_of_arg) = @_;
}
}
\end{code}
+