diff options
Diffstat (limited to 'ghc/driver/ghc-asm-alpha.lprl')
-rw-r--r-- | ghc/driver/ghc-asm-alpha.lprl | 521 |
1 files changed, 0 insertions, 521 deletions
diff --git a/ghc/driver/ghc-asm-alpha.lprl b/ghc/driver/ghc-asm-alpha.lprl deleted file mode 100644 index 23ee45a16f..0000000000 --- a/ghc/driver/ghc-asm-alpha.lprl +++ /dev/null @@ -1,521 +0,0 @@ -%************************************************************************ -%* * -\section[Driver-asm-fiddling]{Fiddling with assembler files (alpha)} -%* * -%************************************************************************ - -Tasks: -\begin{itemize} -\item -Utterly stomp out C functions' prologues and epilogues; i.e., the -stuff to do with the C stack. -\item -Any other required tidying up. -\end{itemize} - -\begin{code} -sub mangle_asm { - local($in_asmf, $out_asmf) = @_; - - # multi-line regexp matching: - local($*) = 1; - local($i, $c); - &init_FUNNY_THINGS(); - - open(INASM, "< $in_asmf") - || &tidy_up_and_die(1,"$Pgm: failed to open `$in_asmf' (to read)\n"); - open(OUTASM,"> $out_asmf") - || &tidy_up_and_die(1,"$Pgm: failed to open `$out_asmf' (to write)\n"); - - # read whole file, divide into "chunks": - # record some info about what we've found... - - @chk = (); # contents of the chunk - $numchks = 0; # number of them - @chkcat = (); # what category of thing in each chunk - @chksymb = (); # what symbol(base) is defined in this chunk - %slowchk = (); # ditto, its regular "slow" entry code - %fastchk = (); # ditto, fast entry code - %closurechk = (); # ditto, the (static) closure - %infochk = (); # given a symbol base, say what chunk its info tbl is in - %vectorchk = (); # ditto, return vector table - %directchk = (); # ditto, direct return code - - $i = 0; - $chkcat[0] = 'misc'; - - while (<INASM>) { -#??? next if /^\.stab.*___stg_split_marker/; -#??? next if /^\.stab.*ghc.*c_ID/; - - next if /^\s*$/; - - if ( /^\s+/ ) { # most common case first -- a simple line! - # duplicated from the bottom - $chk[$i] .= $_; - - } elsif ( /\.\.ng:$/ ) { # Local labels not to be confused with new chunks - $chk[$i] .= $_; - - } elsif ( /^\$C(\d+):$/ ) { - $chk[++$i] .= $_; - $chkcat[$i] = 'string'; - $chksymb[$i] = $1; - - } elsif ( /^__stg_split_marker(\d+):$/ ) { - $chk[++$i] .= $_; - $chkcat[$i] = 'splitmarker'; - $chksymb[$i] = $1; - - } elsif ( /^([A-Za-z0-9_]+)_info:$/ ) { - $symb = $1; - $chk[++$i] .= $_; - $chkcat[$i] = 'infotbl'; - $chksymb[$i] = $symb; - - die "Info table already? $symb; $i\n" if defined($infochk{$symb}); - - $infochk{$symb} = $i; - - } elsif ( /^([A-Za-z0-9_]+)_entry:$/ ) { - $chk[++$i] .= $_; - $chkcat[$i] = 'slow'; - $chksymb[$i] = $1; - - $slowchk{$1} = $i; - - } elsif ( /^([A-Za-z0-9_]+)_fast\d+:$/ ) { - $chk[++$i] .= $_; - $chkcat[$i] = 'fast'; - $chksymb[$i] = $1; - - $fastchk{$1} = $i; - - } elsif ( /^([A-Za-z0-9_]+)_closure:$/ ) { - $chk[++$i] .= $_; - $chkcat[$i] = 'closure'; - $chksymb[$i] = $1; - - $closurechk{$1} = $i; - - } elsif ( /^ghc.*c_ID:/ ) { - $chk[++$i] .= $_; - $chkcat[$i] = 'consist'; - - } elsif ( /^(__gnu_compiled_c|gcc2_compiled\.):/ ) { - ; # toss it - - } elsif ( /^ErrorIO_call_count:/ # HACK!!!! - || /^[A-Za-z0-9_]+\.\d+:$/ - || /^.*_CAT:/ # PROF: _entryname_CAT - || /^CC_.*_struct:/ # PROF: _CC_ccident_struct - || /^.*_done:/ # PROF: _module_done - || /^_module_registered:/ # PROF: _module_registered - ) { - $chk[++$i] .= $_; - $chkcat[$i] = 'data'; - $chksymb[$i] = ''; - - } elsif ( /^(ret_|djn_)/ ) { - $chk[++$i] .= $_; - $chkcat[$i] = 'misc'; - $chksymb[$i] = ''; - - } elsif ( /^vtbl_([A-Za-z0-9_]+):$/ ) { - $chk[++$i] .= $_; - $chkcat[$i] = 'vector'; - $chksymb[$i] = $1; - - $vectorchk{$1} = $i; - - } elsif ( /^([A-Za-z0-9_]+)DirectReturn:$/ ) { - $chk[++$i] .= $_; - $chkcat[$i] = 'direct'; - $chksymb[$i] = $1; - - $directchk{$1} = $i; - - } elsif ( /^[A-Za-z0-9_]+_upd:$/ ) { - $chk[++$i] .= $_; - $chkcat[$i] = 'misc'; - $chksymb[$i] = ''; - - } elsif ( /^[A-Za-z0-9_]/ ) { - local($thing); - chop($thing = $_); - print STDERR "Funny global thing?: $_" - unless $KNOWN_FUNNY_THING{$thing} - || /^_(PRIn|PRStart).*:/ # pointer reversal GC routines - || /^CC_.*:/ # PROF: _CC_ccident - || /^_reg.*:/; # PROF: _reg<module> - $chk[++$i] .= $_; - $chkcat[$i] = 'misc'; - $chksymb[$i] = ''; - - } else { # simple line (duplicated at the top) - $chk[$i] .= $_; - } - } - $numchks = $#chk + 1; - -# print STDERR "\nCLOSURES:\n"; -# foreach $s (sort (keys %closurechk)) { -# print STDERR "$s:\t\t",$closurechk{$s},"\n"; -# } -# print STDERR "\nINFOS:\n"; -# foreach $s (sort (keys %infochk)) { -# print STDERR "$s:\t\t",$infochk{$s},"\n"; -# } -# print STDERR "SLOWS:\n"; -# foreach $s (sort (keys %slowchk)) { -# print STDERR "$s:\t\t",$slowchk{$s},"\n"; -# } -# print STDERR "\nFASTS:\n"; -# foreach $s (sort (keys %fastchk)) { -# print STDERR "$s:\t\t",$fastchk{$s},"\n"; -# } - - # the division into chunks is imperfect; - # we throw some things over the fence into the next - # chunk. - # - # also, there are things we would like to know - # about the whole module before we start spitting - # output. - - # NB: we start meddling at chunk 1, not chunk 0 - - # the first ".rdata" is quite magical; as of GCC 2.7.x, it - # spits a ".quad 0" in after the v first ".rdata"; we - # detect this special case (tossing the ".quad 0")! - $magic_rdata_seen = 0; - - for ($i = 1; $i < $numchks; $i++) { - $c = $chk[$i]; # convenience copy - -# print STDERR "\nCHK $i (BEFORE):\n", $c; - - # pin a funny end-thing on (for easier matching): - $c .= 'FUNNY#END#THING'; - - if ( ! $magic_rdata_seen && $c =~ /^\s*\.rdata\n\t\.quad 0\n\t\.align \d\n/ ) { - $c =~ s/^\s*\.rdata\n\t\.quad 0\n\t\.align (\d)\n/\.rdata\n\t\.align $1\n/; - $magic_rdata_seen = 1; - } - - # pick some end-things and move them to the next chunk - - while ( $c =~ /^(\s*\.align\s+\d+\n)FUNNY#END#THING/ - || $c =~ /^(\s*\.(globl|ent)\s+\S+\n)FUNNY#END#THING/ - || $c =~ /^(\s*\#.*\n)FUNNY#END#THING/ - || $c =~ /^(\s*\.(file|loc)\s+\S+\s+\S+\n)FUNNY#END#THING/ - || $c =~ /^(\s*\.text\n|\s*\.r?data\n)FUNNY#END#THING/ ) { - $to_move = $1; - - if ( $to_move =~ /^\s*(\#|\.(file|globl|ent|loc))/ && $i < ($numchks - 1) ) { - $chk[$i + 1] = $to_move . $chk[$i + 1]; - # otherwise they're tossed - } - - $c =~ s/^.*\nFUNNY#END#THING/FUNNY#END#THING/; - } - - if ($c =~ /^\t\.ent\s+(\S+)/) { - $ent = $1; - # toss all prologue stuff, except for loading gp, and the ..ng address - if (($p, $r) = split(/^\t\.prologue/, $c)) { -# print STDERR "$ent: prologue:\n$p\nrest:\n$r\n"; - if (($keep, $junk) = split(/\.\.ng:/, $p)) { - $c = $keep . "..ng:\n"; - } else { - print STDERR "malformed code block ($ent)?\n" - } - } - $c .= "\t.frame \$30,0,\$26,0\n\t.prologue" . $r; - } - - $c =~ s/FUNNY#END#THING//; - $chk[$i] = $c; # update w/ convenience copy - -# print STDERR "\nCHK $i (AFTER):\n", $c; - } - - # print out the header stuff first - - $chk[0] =~ s/^(\t\.file.*)"(ghc\d+\.c)"/\1"$ifile_root.hc"/; - print OUTASM $chk[0]; - - # print out all the literal strings second - for ($i = 1; $i < $numchks; $i++) { - if ( $chkcat[$i] eq 'string' ) { - print OUTASM "\.rdata\n\t\.align 3\n"; - print OUTASM $chk[$i]; - - $chkcat[$i] = 'DONE ALREADY'; - } - } - - for ($i = 1; $i < $numchks; $i++) { -# print STDERR "$i: cat $chkcat[$i], symb $chksymb[$i]\n"; - - next if $chkcat[$i] eq 'DONE ALREADY'; - - if ( $chkcat[$i] eq 'misc' ) { - print OUTASM "\.text\n\t\.align 3\n"; - print OUTASM $chk[$i]; - - } elsif ( $chkcat[$i] eq 'data' ) { - print OUTASM "\.data\n\t\.align 3\n"; - print OUTASM $chk[$i]; - - } elsif ( $chkcat[$i] eq 'consist' ) { - if ( $chk[$i] =~ /\.ascii.*\)(hsc|cc) (.*)\\11"\n\t\.ascii\s+"(.*)\\0"/ ) { - local($consist) = "$1.$2.$3"; - $consist =~ s/,/./g; - $consist =~ s/\//./g; - $consist =~ s/-/_/g; - $consist =~ s/[^A-Za-z0-9_.]/ZZ/g; # ToDo: properly? - print OUTASM "\.text\n$consist:\n"; - } else { - print STDERR "Couldn't grok consistency: ", $chk[$i]; - } - - } elsif ( $chkcat[$i] eq 'splitmarker' ) { - # we can just re-constitute this one... - # ignore the final split marker, to save an empty object module - # Use _three_ underscores so that ghc-split doesn't get overly complicated - print OUTASM "___stg_split_marker",$chksymb[$i],":\n"; - - } elsif ( $chkcat[$i] eq 'closure' - || $chkcat[$i] eq 'infotbl' - || $chkcat[$i] eq 'slow' - || $chkcat[$i] eq 'fast' ) { # do them in that order - $symb = $chksymb[$i]; - - # CLOSURE - if ( defined($closurechk{$symb}) ) { - print OUTASM "\.data\n\t\.align 3\n"; - print OUTASM $chk[$closurechk{$symb}]; - $chkcat[$closurechk{$symb}] = 'DONE ALREADY'; - } - - # INFO TABLE - if ( defined($infochk{$symb}) ) { - - print OUTASM "\.text\n\t\.align 3\n"; - print OUTASM &rev_tbl($symb, $chk[$infochk{$symb}], 1); - # entry code will be put here! - - # paranoia - if ( $chk[$infochk{$symb}] =~ /\.quad\s+([A-Za-z0-9_]+_entry)$/ - && $1 ne "${symb}_entry" ) { - print STDERR "!!! entry point???\n",$chk[$infochk{$symb}]; - } - - $chkcat[$infochk{$symb}] = 'DONE ALREADY'; - } - - # STD ENTRY POINT - if ( defined($slowchk{$symb}) ) { - - # teach it to drop through to the fast entry point: - $c = $chk[$slowchk{$symb}]; - if ( defined($fastchk{$symb}) ) { - $c =~ s/^\tjmp \$31,\(\$27\),0\n\t\.align 4\n\t\.end/\t.align 4\n\t.end/; - } - - # NB: no very good way to look for "dangling" references - # to fast-entry pt - - print OUTASM "\.text\n\t\.align 3\n"; - print OUTASM $c; - $chkcat[$slowchk{$symb}] = 'DONE ALREADY'; - } - - # FAST ENTRY POINT - if ( defined($fastchk{$symb}) ) { - $c = $chk[$fastchk{$symb}]; - if ( ! defined($slowchk{$symb}) ) { - print OUTASM "\.text\n\t\.align 3\n"; - } - print OUTASM $c; - $chkcat[$fastchk{$symb}] = 'DONE ALREADY'; - } - - } elsif ( $chkcat[$i] eq 'vector' - || $chkcat[$i] eq 'direct' ) { # do them in that order - $symb = $chksymb[$i]; - - # VECTOR TABLE - if ( defined($vectorchk{$symb}) ) { - print OUTASM "\.text\n\t\.align 3\n"; - print OUTASM &rev_tbl($symb, $chk[$vectorchk{$symb}], 0); - # direct return code will be put here! - $chkcat[$vectorchk{$symb}] = 'DONE ALREADY'; - } - - # DIRECT RETURN - if ( defined($directchk{$symb}) ) { - print OUTASM "\.text\n\t\.align 3\n"; - print OUTASM $chk[$directchk{$symb}]; - $chkcat[$directchk{$symb}] = 'DONE ALREADY'; - } else { - # The commented nop is for the splitter, to ensure - # that no module ends with a label as the very last - # thing. (The linker will adjust the label to point - # to the first code word of the next module linked in, - # even if alignment constraints cause the label to move!) - - print OUTASM "\t# nop\n"; - } - } else { - &tidy_up_and_die(1,"$Pgm: unknown chkcat (ghc-asm alpha)\n$chkcat[$i]\n$chk[$i]\n"); - } - } - - # finished: - close(OUTASM) || &tidy_up_and_die(1,"Failed writing to $out_asmf\n"); - close(INASM) || &tidy_up_and_die(1,"Failed reading from $in_asmf\n"); -} -\end{code} - -\begin{code} -sub init_FUNNY_THINGS { - %KNOWN_FUNNY_THING = ( - 'CheckHeapCode:', 1, - 'CommonUnderflow:', 1, - 'Continue:', 1, - 'EnterNodeCode:', 1, - 'ErrorIO_call_count:', 1, - 'ErrorIO_innards:', 1, - 'IndUpdRetDir:', 1, - 'IndUpdRetV0:', 1, - 'IndUpdRetV1:', 1, - 'IndUpdRetV2:', 1, - 'IndUpdRetV3:', 1, - 'IndUpdRetV4:', 1, - 'IndUpdRetV5:', 1, - 'IndUpdRetV6:', 1, - 'IndUpdRetV7:', 1, - 'PrimUnderflow:', 1, - 'StackUnderflowEnterNode:', 1, - 'StdErrorCode:', 1, - 'UnderflowVect0:', 1, - 'UnderflowVect1:', 1, - 'UnderflowVect2:', 1, - 'UnderflowVect3:', 1, - 'UnderflowVect4:', 1, - 'UnderflowVect5:', 1, - 'UnderflowVect6:', 1, - 'UnderflowVect7:', 1, - 'UpdErr:', 1, - 'UpdatePAP:', 1, - 'WorldStateToken:', 1, - '_Enter_Internal:', 1, - '_PRMarking_MarkNextAStack:', 1, - '_PRMarking_MarkNextBStack:', 1, - '_PRMarking_MarkNextCAF:', 1, - '_PRMarking_MarkNextGA:', 1, - '_PRMarking_MarkNextRoot:', 1, - '_PRMarking_MarkNextSpark:', 1, - '_Scavenge_Forward_Ref:', 1, - '__std_entry_error__:', 1, - '_startMarkWorld:', 1, - 'resumeThread:', 1, - 'startCcRegisteringWorld:', 1, - 'startEnterFloat:', 1, - 'startEnterInt:', 1, - 'startPerformIO:', 1, - 'startStgWorld:', 1, - 'stopPerformIO:', 1 - ); -} -\end{code} - -The following table reversal is used for both info tables and return -vectors. In both cases, we remove the first entry from the table, -reverse the table, put the label at the end, and paste some code -(that which is normally referred to by the first entry in the table) -right after the table itself. (The code pasting is done elsewhere.) - -\begin{code} -sub rev_tbl { - local($symb, $tbl, $discard1) = @_; - - local($before) = ''; - local($label) = ''; - local(@words) = (); - local($after) = ''; - local(@lines) = split(/\n/, $tbl); - local($i); - - for ($i = 0; $i <= $#lines && $lines[$i] !~ /^\t\.quad\s+/; $i++) { - $label .= $lines[$i] . "\n", - next if $lines[$i] =~ /^[A-Za-z0-9_]+:$/ - || $lines[$i] =~ /^\t\.globl/; - - $before .= $lines[$i] . "\n"; # otherwise... - } - - for ( ; $i <= $#lines && $lines[$i] =~ /^\t\.quad\s+/; $i++) { - push(@words, $lines[$i]); - } - # now throw away the first word (entry code): - shift(@words) if $discard1; - - for (; $i <= $#lines; $i++) { - $after .= $lines[$i] . "\n"; - } - - # If we have anonymous text (not part of a procedure), the linker - # may complain about missing exception information. Bleh. - if ($label =~ /^([A-Za-z0-9_]+):$/) { - $before = "\t.ent $1\n" . $before; - $after .= "\t.end $1\n"; - } - - $tbl = $before . join("\n", (reverse @words)) . "\n" . $label . $after; - -# print STDERR "before=$before\n"; -# print STDERR "label=$label\n"; -# print STDERR "words=",(reverse @words),"\n"; -# print STDERR "after=$after\n"; - - $tbl; -} -\end{code} - -%************************************************************************ -%* * -\subsection[Driver-asm-info]{Collect interesting (static) info from an assembler file} -%* * -%************************************************************************ - -How many times is each asm instruction used? - -\begin{code} -%AsmInsn = (); # init - -sub dump_asm_insn_counts { - local($asmf) = @_; - - open(INASM, "< $asmf") || &tidy_up_and_die(1,"$Pgm: failed to open `$asmf' (to read)\n"); - while (<INASM>) { - if ( /^\t([a-z][a-z0-9]+)\b/ ) { - $AsmInsn{$1} ++; - } - } - close(INASM) || &tidy_up_and_die(1,"Failed reading from $asmf\n"); - - # OK, now print what we collected (to stderr) - foreach $i (sort (keys %AsmInsn)) { - print STDERR "INSN:: $i\t",$AsmInsn{$i},"\n"; - } -} - -sub dump_asm_globals_info { -} - -# make "require"r happy... -1; -\end{code} |