$T_HDR_srt = "\.text\n\t\.align 3\n";
$T_HDR_info = "\.text\n\t\.align 3\n";
$T_HDR_entry = "\.text\n\t\.align 3\n";
- $T_HDR_fast = "\.text\n\t\.align 3\n";
$T_HDR_vector = "\.text\n\t\.align 3\n";
$T_HDR_direct = "\.text\n\t\.align 3\n";
$T_create_word = "\t.quad";
$T_HDR_srt = "\t.SPACE \$PRIVATE\$\n\t.SUBSPA \$DATA\$\n\t\.align 4\n";
$T_HDR_info = "\t.SPACE \$TEXT\$\n\t.SUBSPA \$CODE\$\n\t\.align 4\n";
$T_HDR_entry = "\t.SPACE \$TEXT\$\n\t.SUBSPA \$CODE\$\n\t\.align 4\n";
- $T_HDR_fast = "\t.SPACE \$TEXT\$\n\t.SUBSPA \$CODE\$\n\t\.align 4\n";
$T_HDR_vector = "\t.SPACE \$TEXT\$\n\t.SUBSPA \$CODE\$\n\t\.align 4\n";
$T_HDR_direct = "\t.SPACE \$TEXT\$\n\t.SUBSPA \$CODE\$\n\t\.align 4\n";
$T_create_word = "\t.word";
$T_HDR_data = "\.data\n\t\.align 2\n";
$T_HDR_consist = "\.text\n";
$T_HDR_closure = "\.data\n\t\.align 2\n";
- $T_HDR_closure = "\.data\n\t\.align 2\n\t.long 0\n" if ( $TargetPlatform =~ /.*-mingw32$/ );
$T_HDR_srt = "\.text\n\t\.align 2\n";
$T_HDR_info = "\.text\n\t\.align 2\n"; # NB: requires padding
$T_HDR_entry = "\.text\n"; # no .align so we're right next to _info (arguably wrong...?)
- $T_HDR_fast = "\.text\n\t\.align 2,0x90\n";
$T_HDR_vector = "\.text\n\t\.align 2\n"; # NB: requires padding
$T_HDR_direct = "\.text\n\t\.align 2,0x90\n";
$T_create_word = "\t.word";
$T_X86_PRE_LLBL = '.L';
$T_X86_BADJMP = '^\tjmp\s+[^\.\*]';
- $T_MOVE_DIRVS = '^(\s*(\.(p2)?align\s+\d+(,\s*0x90)?|\.globl\s+\S+|\.text|\.data|\.section\s+.*|\.type\s+.*|\.Lfe.*\n\s*\.size\s+.*|\.size\s+.*|\.ident.*)\n)';
- $T_COPY_DIRVS = '\.(globl)';
+ $T_MOVE_DIRVS = '^(\s*(\.(p2)?align\s+\d+(,\s*0x90)?|\.globl\s+\S+|\.text|\.data|\.section\s+.*|\.type\s+.*|\.size\s+\S+,\d+|\.ident.*)\n)';
+ $T_COPY_DIRVS = '^\s*\.(globl|type|size)';
if ( $TargetPlatform =~ /freebsd|netbsd/ ) {
$T_hsc_cc_PAT = '\.ascii.*\)(hsc|cc) (.*)\\\\11"\n\t\.ascii\s+"(.*)\\\\0"';
$T_HDR_srt = "\.text\n\t\.align 4\n"; # ToDo: change align?
$T_HDR_info = "\.text\n\t\.align 4\n"; # NB: requires padding
$T_HDR_entry = "\.text\n"; # no .align so we're right next to _info (arguably wrong...?)
- $T_HDR_fast = "\.text\n\t\.align 4\n";
$T_HDR_vector = "\.text\n\t\.align 4\n"; # NB: requires padding
$T_HDR_direct = "\.text\n\t\.align 4\n";
$T_create_word = "\t.word";
$T_HDR_srt = "\.text\n\t\.align 8\n";
$T_HDR_info = "\.text\n\t\.align 8\n";
$T_HDR_entry = "\.text\n\t\.align 16\n";
- $T_HDR_fast = "\.text\n\t\.align 16\n";
$T_HDR_vector = "\.text\n\t\.align 8\n";
$T_HDR_direct = "\.text\n\t\.align 8\n";
$T_create_word = "\t.word";
$T_HDR_srt = "\.text\n\t\.even\n";
$T_HDR_info = "\.text\n\t\.even\n";
$T_HDR_entry = "\.text\n\t\.even\n";
- $T_HDR_fast = "\.text\n\t\.even\n";
$T_HDR_vector = "\.text\n\t\.even\n";
$T_HDR_direct = "\.text\n\t\.even\n";
$T_create_word = "\t.long";
$T_HDR_srt = "\t\.text\n\t\.align 2\n";
$T_HDR_info = "\t\.text\n\t\.align 2\n";
$T_HDR_entry = "\t\.text\n\t\.align 2\n";
- $T_HDR_fast = "\t\.text\n\t\.align 2\n";
$T_HDR_vector = "\t\.text\n\t\.align 2\n";
$T_HDR_direct = "\t\.text\n\t\.align 2\n";
$T_create_word = "\t.word";
$T_HDR_srt = "\t\.text\n\t\.align 2\n";
$T_HDR_info = "\t\.text\n\t\.align 2\n";
$T_HDR_entry = "\t\.text\n\t\.align 2\n";
- $T_HDR_fast = "\t\.text\n\t\.align 2\n";
$T_HDR_vector = "\t\.text\n\t\.align 2\n";
$T_HDR_direct = "\t\.text\n\t\.align 2\n";
$T_create_word = "\t.long";
$T_HDR_srt = "\.data\n\t\.align 4\n";
$T_HDR_info = "\.text\n\t\.align 4\n";
$T_HDR_entry = "\.text\n\t\.align 4\n";
- $T_HDR_fast = "\.text\n\t\.align 4\n";
$T_HDR_vector = "\.text\n\t\.align 4\n";
$T_HDR_direct = "\.text\n\t\.align 4\n";
$T_create_word = "\t.word";
$T_HDR_srt = "\.data\n\t\.align 4\n";
$T_HDR_info = "\.text\n\t\.align 4\n";
$T_HDR_entry = "\.text\n\t\.align 4\n";
- $T_HDR_fast = "\.text\n\t\.align 4\n";
$T_HDR_vector = "\.text\n\t\.align 4\n";
$T_HDR_direct = "\.text\n\t\.align 4\n";
$T_create_word = "\t.word";
print STDERR "T_HDR_closure: $T_HDR_closure\n";
print STDERR "T_HDR_info: $T_HDR_info\n";
print STDERR "T_HDR_entry: $T_HDR_entry\n";
-print STDERR "T_HDR_fast: $T_HDR_fast\n";
print STDERR "T_HDR_vector: $T_HDR_vector\n";
print STDERR "T_HDR_direct: $T_HDR_direct\n";
}
$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
+ %entrychk = (); # ditto, its entry code
%closurechk = (); # ditto, the (static) closure
%srtchk = (); # ditto, its SRT (for top-level things)
%infochk = (); # given a symbol base, say what chunk its info tbl is in
} elsif ( /^${T_US}([A-Za-z0-9_]+)_(entry|ret)${T_POST_LBL}$/o ) {
$chk[++$i] = $_;
- $chkcat[$i] = 'slow';
- $chksymb[$i] = $1;
-
- $slowchk{$1} = $i;
-
- } elsif ( /^${T_US}([A-Za-z0-9_]+)_fast\d*${T_POST_LBL}$/o ) {
- $chk[++$i] = $_;
- $chkcat[$i] = 'fast';
+ $chkcat[$i] = 'entry';
$chksymb[$i] = $1;
- $fastchk{$1} = $i;
+ $entrychk{$1} = $i;
} elsif ( /^${T_US}([A-Za-z0-9_]+)_closure${T_POST_LBL}$/o ) {
$chk[++$i] = $_;
$chkcat[$i] = 'data';
$chksymb[$i] = '';
- } elsif ( /^${T_US}ghc.*c_ID${T_POST_LBL}/o ) {
- $chk[++$i] = $_;
- $chkcat[$i] = 'consist';
-
} elsif ( /^(${T_US}__gnu_compiled_c|gcc2_compiled\.)${T_POST_LBL}/o ) {
; # toss it
|| ! /^L\$\d+$/ ) ) {
local($thing);
chop($thing = $_);
- print STDERR "Warning: retaining unknown function `$_' in output from C compiler"
+ $thing =~ s/:$//;
+ print STDERR "Warning: retaining unknown function \`$thing' in output from C compiler\n"
unless # $KNOWN_FUNNY_THING{$thing}
/^${T_US}stg_.*${T_POST_LBL}$/o # RTS internals
|| /^${T_US}__stg_.*${T_POST_LBL}$/o # more RTS internals
|| /^${T_US}__fexp_.*${T_POST_LBL}$/o # foreign export
+ || /^${T_US}.*_slow${T_POST_LBL}$/o # slow entry
|| /^${T_US}__stginit.*${T_POST_LBL}$/o # __stginit<module>
|| /^${T_US}.*_btm${T_POST_LBL}$/o # large bitmaps
+ || /^${T_US}.*_fast${T_POST_LBL}$/o # primops
|| /^${T_US}.*_closure_tbl${T_POST_LBL}$/o # closure tables
|| /^_uname:/o; # x86/Solaris2
$chk[++$i] = $_;
$chk[++$i] = $_;
$chkcat[$i] = 'dyld';
$chksymb[$i] = '';
+ } elsif ( $TargetPlatform =~ /^powerpc-apple-.*/ && /^\.symbol_stub/ )
+ {
+ $chk[++$i] = $_;
+ $chkcat[$i] = 'dyld';
+ $chksymb[$i] = '';
} elsif ( $TargetPlatform =~ /^powerpc-apple-.*/ && /^\.lazy_symbol_pointer/ )
{
$chk[++$i] = $_;
$p =~ s/^\tpushl\s+\%edi\n//;
$p =~ s/^\tpushl\s+\%esi\n//;
$p =~ s/^\tpushl\s+\%ebx\n//;
+ $p =~ s/^\tmovl\s+\%esi,\s*\d*\(\%esp\)\n//;
+ $p =~ s/^\tmovl\s+\%edi,\s*\d*\(\%esp\)\n//;
$p =~ s/^\tsubl\s+\$\d+,\s*\%esp\n//;
$p =~ s/^\tmovl\s+\$\d+,\s*\%eax\n\tcall\s+__alloca\n// if ($TargetPlatform =~ /^.*-cygwin32/);
# GCC 3.1 is in the habit of adding spurious writes to the
# stack in the prologue. Just to be on the safe side,
# chuck these over the fence into the main code.
- while ($p =~ /^\tmovl\s+(\$\d+|\%edi),\s*\d*\(\%esp\)\n/) {
+ while ($p =~ /^\tmovl\s+\$\d+,\s*\d*\(\%esp\)\n/) {
# print "Spurious instruction: $&";
$p = $` . $';
$r = $& . $r;
$p =~ s/^\tbcl 20,31,L\d+\$pb\n//;
$p =~ s/^L\d+\$pb:\n//;
$p =~ s/^\tmflr r31\n//;
+
+ # This is bad: GCC 3 seems to zero-fill some local variables in the prologue
+ # under some circumstances, only when generating position dependent code.
+ # I have no idea why, and I don't think it is necessary, so let's toss it.
+ $p =~ s/^\tli r\d+,0\n//g;
+ $p =~ s/^\tstw r\d+,\d+\(r1\)\n//g;
} else {
print STDERR "$Pgm: unknown prologue mangling? $TargetPlatform\n";
}
# HWL HACK: dont die, just print a warning
#print stderr "HWL: this should die! Prologue junk?: $p\n" if $p =~ /^\t[^\.]/;
- die "Prologue junk?: $p\n" if $p =~ /^\t[^\.]/;
+ die "Prologue junk?: $p\n" if $p =~ /^\s+[^\s\.]/;
if ($TargetPlatform =~ /^powerpc-apple-.*/ && $pcrel_label ne "") {
# on PowerPC, we have to keep a part of the prologue
# blah_closure:
# ...
#
- if ( $TargetPlatform =~ /^(i386|sparc)/ && $to_move =~ /${T_COPY_DIRVS}/ ) {
+ if ( $TargetPlatform =~ /^(i386|sparc|powerpc)/ && $to_move =~ /${T_COPY_DIRVS}/ ) {
$j = $i + 1;
while ( $j < $numchks && $chk[$j] =~ /$T_CONST_LBL/) {
$j++;
} elsif ( $chkcat[$i] eq 'closure'
|| $chkcat[$i] eq 'srt'
|| $chkcat[$i] eq 'infotbl'
- || $chkcat[$i] eq 'slow'
- || $chkcat[$i] eq 'fast' ) { # do them in that order
+ || $chkcat[$i] eq 'entry') { # do them in that order
$symb = $chksymb[$i];
# CLOSURE
}
# 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}) ) {
- if ( $TargetPlatform =~ /^alpha-/ ) {
- $c =~ s/^\tjmp \$31,\(\$27\),0\n\t\.align 4\n\t\.end/\t.align 4\n\t.end/;
- } elsif ( $TargetPlatform =~ /^hppa/ ) {
- $c =~ s/^\s+ldil.*\n\s+ldo.*\n\s+bv.*\n(.*\n)?\s+\.EXIT/$1\t.EXIT/;
- } elsif ( $TargetPlatform =~ /^i386-/ ) {
- # Reg alloc depending, gcc generated code may jump to the fast entry point via
- # a number of registers.
- $c =~ s/^\tmovl\s+\$${T_US}${symb}_fast\d*,\s*\%edx\n\tjmp\s+\*\%edx\n//;
- $c =~ s/^\tmovl\s+\$${T_US}${symb}_fast\d*,\s*\%ecx\n\tjmp\s+\*\%ecx\n//;
- $c =~ s/^\tmovl\s+\$${T_US}${symb}_fast\d*,\s*\%eax\n\tjmp\s+\*\%eax\n//;
- # The next two only apply if we're not stealing %esi or %edi.
- $c =~ s/^\tmovl\s+\$${T_US}${symb}_fast\d*,\s*\%esi\n\tjmp\s+\*\%esi\n// if ($StolenX86Regs < 3);
- $c =~ s/^\tmovl\s+\$${T_US}${symb}_fast\d*,\s*\%edi\n\tjmp\s+\*\%edi\n// if ($StolenX86Regs < 4);
- } elsif ( $TargetPlatform =~ /^ia64-/ ) {
- #$c =~ s/^\tbr\.few ${symb}_fast\d*#\n\t;;\n(\t;;\n\t\.endp ${symb}_entry#\n)/$1/;
- $c =~ s/^\tbr\.few ${symb}_fast\d*#\n(\t;;\n\t\.endp ${symb}_entry#\n)/$1/;
- } elsif ( $TargetPlatform =~ /^mips-/ ) {
- $c =~ s/^\tjmp \$31,\(\$27\),0\n\t\.align 4\n\t\.end/\t.align 4\n\t.end/;
- } elsif ( $TargetPlatform =~ /^m68k-/ ) {
- $c =~ s/^\tjmp ${T_US}${symb}_fast\d+.*\n\tnop\n//;
- $c =~ s/^\tjmp ${T_US}${symb}_fast\d+.*\n//;
- } elsif ( $TargetPlatform =~ /^powerpc-apple-.*/ ) {
- $c =~ s/^\taddis r9,r31,ha16\(L_${symb}_fast\d*\$non_lazy_ptr-L\d+\$pb\)\n\tlwz r9,lo16\(L_${symb}_fast\d*\$non_lazy_ptr-L\d+\$pb\)\(r9\)\n\tmtctr r9\n\tbctr\n//;
- # addis r9,r31,ha16(L_XXXX_fast3$non_lazy_ptr-L32$pb)
- # lwz r9,lo16(L_XXXX_fast3$non_lazy_ptr-L32$pb)(r9)
- # mtctr r9
- # bctr
- } elsif ( $TargetPlatform =~ /^sparc-/ ) {
- $c =~ s/^\tcall\s+${T_US}${symb}_fast\d+,.*\n\t\s*nop\n//;
- $c =~ s/^\tcall\s+${T_US}${symb}_fast\d+,.*\n(\t\s*[a-z].*\n)/$1/;
- } else {
- print STDERR "$Pgm: mystery slow-fast dropthrough: $TargetPlatform\n";
- }
- }
+ if ( defined($entrychk{$symb}) ) {
- if ( $TargetPlatform !~ /^(alpha-|hppa|mips-|powerpc-apple-)/) {
- # On alphas, hppa: no very good way to look for "dangling"
- # references to fast-entry point.
- # (questionable re hppa and mips...)
- print STDERR "still has jump to fast entry point:\n$c"
- if $c =~ /\b${T_US}${symb}_fast/;
- }
+ $c = $chk[$entrychk{$symb}];
print OUTASM $T_HDR_entry;
&print_doctored($c, 1); # NB: the 1!!!
- $chkcat[$slowchk{$symb}] = 'DONE ALREADY';
+ $chkcat[$entrychk{$symb}] = 'DONE ALREADY';
}
- # FAST ENTRY POINT
- if ( defined($fastchk{$symb}) ) {
- $c = $chk[$fastchk{$symb}];
- if ( ! defined($slowchk{$symb})
- # ToDo: the || clause can go once we're no longer
- # concerned about producing exactly the same output as before
-#OLD: || $TargetPlatform =~ /^(m68k|sparc|i386)-/
- ) {
- print OUTASM $T_HDR_fast;
- }
-
- &print_doctored($c, 0);
- $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 $T_HDR_vector;
-
print OUTASM &rev_tbl($symb, $chk[$vectorchk{$symb}], 0);
- # DO NOT DELETE THE NEXT LINE. It fixes a rather subtle GC bug
- # which showed up as a segfault reported by Ryszard Kubiak.
- # Problem is with vector tables. They wind up as follows:
- # .word some-word
- # .word some-other-word
- # fooble_vtbl:
- # Problem is that we want the label fooble_vtbl to be considered
- # in the same section as the vtbl itself, but the label actually
- # lives at the next word along. If a data segment should happen
- # to immediately follow the vtbl, as it can in GHCi, the label will
- # be malclassified as in the data rather than text segment (during
- # GC), and so we will regard references to it as static closure
- # pointers rather than as code pointers, which is an error which
- # usually crashes the garbage collectors.
- # To fix this, we place a dummy word after the label, so as to
- # ensure that the label is in the same segment as the vtbl proper.
- # The native code generator has an analogous fix; see
- # ghc/compiler/nativeGen/AbsCStixGen.lhs line 107.
- print OUTASM "${T_create_word} 0\n";
# direct return code will be put here!
$chkcat[$vectorchk{$symb}] = 'DONE ALREADY';
# Offsets into register table - you'd better update these magic
# numbers should you change its contents!
# local($OFFSET_R1)=0; No offset for R1 in new RTS.
- local($OFFSET_Hp)=92;
+ local($OFFSET_Hp)=88;
# Note funky ".=" stuff; we're *adding* to these _patch guys
if ( $StolenX86Regs <= 2
}
}
- # now throw away the first word (SRT) iff it is empty.
+ # Now throw away any initial zero word from the table. This is a hack
+ # that lets us reduce the size of info tables when the SRT field is not
+ # needed: see comments StgFunInfoTable in InfoTables.h.
+ #
# The .zero business is for Linux/ELF.
# The .skip business is for Sparc/Solaris/ELF.
# The .blockz business is for HPPA.
- if ($discard1 && $words[0] =~ /^\t?(${T_DOT_WORD}\s+0|\.zero\s+4|\.skip\s+4|\.blockz\s+4)/) {
- shift(@words)
- }
+# if ($discard1) {
+# if ($words[0] =~ /^\t?(${T_DOT_WORD}\s+0|\.zero\s+4|\.skip\s+4|\.blockz\s+4)/) {
+# shift(@words);
+# }
+# }
for (; $i <= $#lines; $i++) {
$after .= $lines[$i] . "\n";