Skip to content
Snippets Groups Projects
Commit 5388d254 authored by Will Partain's avatar Will Partain
Browse files

[project @ 2000-06-13 15:35:29 by partain]

partain 1.3 changes to 960626
parent 7ecb743e
No related merge requests found
......@@ -64,7 +64,7 @@ sub init_TARGET_STUFF {
$T_hsc_cc_PAT = '\.ascii.*\)(hsc|cc) (.*)\\\\11"\n\t\.ascii\s+"(.*)\\\\0"';
$T_DOT_WORD = '\.quad';
$T_DOT_GLOBAL = '^\t\.globl';
$T_DOT_GLOBAL = "\t\.globl";
$T_HDR_literal = "\.rdata\n\t\.align 3\n";
$T_HDR_misc = "\.text\n\t\.align 3\n";
$T_HDR_data = "\.data\n\t\.align 3\n";
......@@ -91,7 +91,7 @@ sub init_TARGET_STUFF {
$T_hsc_cc_PAT = '\.STRING.*\)(hsc|cc) (.*)\\\\x09(.*)\\\\x00';
$T_DOT_WORD = '\.word';
$T_DOT_GLOBAL = '^\s+\.EXPORT';
$T_DOT_GLOBAL = '\s+\.EXPORT';
$T_HDR_literal = "\t.SPACE \$TEXT\$\n\t.SUBSPA \$LIT\$\n";
$T_HDR_misc = "\t.SPACE \$TEXT\$\n\t.SUBSPA \$CODE\$\n\t\.align 4\n";
$T_HDR_data = "\t.SPACE \$PRIVATE\$\n\t.SUBSPA \$DATA\$\n\t\.align 4\n";
......@@ -121,11 +121,11 @@ sub init_TARGET_STUFF {
$T_hsc_cc_PAT = '\.ascii.*\)(hsc|cc) (.*)\\\\11"\n\t\.ascii\s+"(.*)\\\\0"';
$T_DOT_WORD = '\.long';
$T_DOT_GLOBAL = '\.globl';
$T_HDR_literal = "\.text\n\t\.align 2\n";
$T_HDR_literal = "\.text\n\t\.align 2\n"; # .align 4 is 486-cache friendly
$T_HDR_misc = "\.text\n\t\.align 2,0x90\n";
$T_HDR_data = "\.data\n\t\.align 2\n";
$T_HDR_data = "\.data\n\t\.align 2\n"; # ToDo: change align??
$T_HDR_consist = "\.text\n";
$T_HDR_closure = "\.data\n\t\.align 2\n";
$T_HDR_closure = "\.data\n\t\.align 2\n"; # ToDo: change align?
$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";
......@@ -138,8 +138,7 @@ sub init_TARGET_STUFF {
$T_STABBY = 0; # 1 iff .stab things (usually if a.out format)
$T_US = ''; # _ if symbols have an underscore on the front
$T_DO_GC = 'PerformGC_wrapper';
$T_PRE_APP = # regexp that says what comes before APP/NO_APP
($TargetPlatform =~ /-linux$/) ? '#' : '/' ;
$T_PRE_APP = '/'; # regexp that says what comes before APP/NO_APP
$T_CONST_LBL = '^\.LC(\d+):$'; # regexp for what such a lbl looks like
$T_POST_LBL = ':';
$T_X86_PRE_LLBL_PAT = '\.L';
......@@ -173,7 +172,7 @@ sub init_TARGET_STUFF {
$T_CONST_LBL = '^LC(\d+):$';
$T_POST_LBL = ':';
$T_MOVE_DIRVS = '^(\s*(\.align\s+\d+|\.proc\s+\d+|\.const|\.cstring|\.globl\s+\S+|\.text|\.data|\.even|\.stab[^n].*)\n)';
$T_MOVE_DIRVS = '(\s*(\.align\s+\d+|\.proc\s+\d+|\.const|\.cstring|\.globl\s+\S+|\.text|\.data|\.even|\.stab[^n].*)\n)';
$T_COPY_DIRVS = '\.(globl|proc|stab)';
$T_hsc_cc_PAT = '\.ascii.*\)(hsc|cc) (.*)\\\\11"\n\t\.ascii\s+"(.*)\\\\0"';
......@@ -200,12 +199,12 @@ sub init_TARGET_STUFF {
$T_CONST_LBL = '^\$LC(\d+):$'; # regexp for what such a lbl looks like
$T_POST_LBL = ':';
$T_MOVE_DIRVS = '^(\s*(\.align\s+\d+|\.(globl|ent)\s+\S+|\.text|\.r?data)\n)';
$T_MOVE_DIRVS = '(\s*(\.align\s+\d+|\.(globl|ent)\s+\S+|\.text|\.r?data)\n)';
$T_COPY_DIRVS = '\.(globl|ent)';
$T_hsc_cc_PAT = 'I WAS TOO LAZY TO DO THIS BIT (WDP 95/05)';
$T_DOT_WORD = '\.word';
$T_DOT_GLOBAL = '^\t\.globl';
$T_DOT_GLOBAL = '\t\.globl';
$T_HDR_literal = "\t\.rdata\n\t\.align 2\n";
$T_HDR_misc = "\t\.text\n\t\.align 2\n";
$T_HDR_data = "\t\.data\n\t\.align 2\n";
......@@ -221,28 +220,28 @@ sub init_TARGET_STUFF {
} elsif ( $TargetPlatform =~ /^powerpc-.*/ ) {
$T_STABBY = 0; # 1 iff .stab things (usually if a.out format)
$T_US = ''; # _ if symbols have an underscore on the front
$T_US = '\.'; # _ if symbols have an underscore on the front
$T_DO_GC = 'PerformGC_wrapper';
$T_PRE_APP = 'NOT APPLICABLE'; # regexp that says what comes before APP/NO_APP
$T_CONST_LBL = '^LC\.\.(\d+):$'; # regexp for what such a lbl looks like
$T_POST_LBL = ':';
$T_MOVE_DIRVS = '^(\s*(\.toc|.csect \S+|\.l?globl \S+|\.align \d+)\n)';
$T_COPY_DIRVS = '\.(l?globl)';
$T_MOVE_DIRVS = '^(\s*(\.align\s+\d+(,0x90)?|\.globl\s+\S+|\.text|\.data|\.section\s+.*|\.type\s+.*|\.Lfe.*\n\t\.size\s+.*|\.size\s+.*|\.ident.*)\n)';
$T_COPY_DIRVS = '\.(globl)';
$T_hsc_cc_PAT = '\.string.*\)(hsc|cc) (.*)\\\\t(.*)"';
$T_DOT_WORD = '\.long';
$T_DOT_GLOBAL = '\.globl';
$T_HDR_literal = "\.section\t\.rodata\n";
$T_HDR_misc = "\.text\n\t\.align 2\n";
$T_HDR_data = "\.data\n\t\.align 2\n";
$T_HDR_literal = "\.section\t\.rodata\n"; # or just use .text??? (WDP 95/11)
$T_HDR_misc = "\.text\n\t\.align 16\n";
$T_HDR_data = "\.data\n\t\.align 4\n"; # ToDo: change align??
$T_HDR_consist = "\.text\n";
$T_HDR_closure = "\.data\n\t\.align 2\n";
$T_HDR_info = "\.text\n\t\.align 2\n";
$T_HDR_entry = "\.text\n";
$T_HDR_fast = "\.text\n\t\.align 2\n";
$T_HDR_vector = "\.text\n\t\.align 2\n";
$T_HDR_direct = "\.text\n\t\.align 2\n";
$T_HDR_closure = "\.data\n\t\.align 4\n"; # ToDo: change align?
$T_HDR_info = "\.text\n\t\.align 16\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 16\n";
$T_HDR_vector = "\.text\n\t\.align 16\n"; # NB: requires padding
$T_HDR_direct = "\.text\n\t\.align 16\n";
#--------------------------------------------------------#
} elsif ( $TargetPlatform =~ /^sparc-.*-solaris2/ ) {
......@@ -259,7 +258,7 @@ sub init_TARGET_STUFF {
$T_hsc_cc_PAT = '\.asciz.*\)(hsc|cc) (.*)\\\\t(.*)"';
$T_DOT_WORD = '\.word';
$T_DOT_GLOBAL = '^\t\.global';
$T_DOT_GLOBAL = '\.global';
$T_HDR_literal = "\.text\n\t\.align 8\n";
$T_HDR_misc = "\.text\n\t\.align 4\n";
$T_HDR_data = "\.data\n\t\.align 8\n";
......@@ -380,9 +379,7 @@ sub mangle_asm {
next if /^;/ && $TargetPlatform =~ /^hppa/;
next if /(^$|^\t\.file\t|^ # )/ && $TargetPlatform =~ /^(mips|powerpc)-/;
last if /^_section_\.text:$/ && $TargetPlatform =~ /^powerpc-/;
next if /(^$|^\t\.file\t|^ # )/ && $TargetPlatform =~ /^mips-/;
if ( $TargetPlatform =~ /^mips-/
&& /^\t\.(globl \S+ \.text|comm\t)/ ) {
......@@ -508,9 +505,7 @@ sub mangle_asm {
} elsif ( /^${T_US}[A-Za-z0-9_]/o
&& ( $TargetPlatform !~ /^hppa/ # need to avoid local labels in this case
|| ! /^L\$\d+$/ )
&& ( $TargetPlatform !~ /^powerpc/ # ditto
|| ! /^(L\.\.\d+|LT\.\..*):$/ ) ) {
|| /^L\$\d+$/ ) ) {
local($thing);
chop($thing = $_);
print STDERR "Funny global thing?: $_"
......@@ -589,20 +584,13 @@ sub mangle_asm {
print STDERR "$Pgm: unknown prologue mangling? $TargetPlatform\n";
}
die "Prologue junk?: $p\n" if $p =~ /^\t[^\.]/
&& $TargetPlatform !~ /^powerpc-/; #ToDo: remove test
die "Prologue junk?: $p\n" if $p =~ /^\t[^\.]/;
# glue together what's left
$c = $p . $r;
$c =~ s/\n\t\n/\n/; # junk blank line
}
}
if ( $TargetPlatform =~ /^mips-/ ) {
# MIPS: first, this basic sequence may occur "--- END ---" or not
$c =~ s/^\tlw\t\$31,\d+\(\$sp\)\n\taddu\t\$sp,\$sp,\d+\n\tj\t\$31\n\t\.end/\t\.end/;
}
# toss all epilogue stuff; again, paranoidly
if ( $c =~ /--- END ---/ ) {
if (($r, $e) = split(/--- END ---/, $c)) {
......@@ -622,8 +610,7 @@ sub mangle_asm {
} else {
print STDERR "$Pgm: unknown epilogue mangling? $TargetPlatform\n";
}
die "Epilogue junk?: $e\n" if $e =~ /^\t[^\.]/
&& $TargetPlatform !~ /^powerpc-/; #ToDo: remove test
die "Epilogue junk?: $e\n" if $e =~ /^\t[^\.]/;
# glue together what's left
$c = $r . $e;
......@@ -643,7 +630,7 @@ sub mangle_asm {
# On Alphas, the prologue mangling is done a little later (below)
# toss all calls to __DISCARD__
$c =~ s/^\t(call|jbsr|jal)\s+${T_US}__DISCARD__\n//go;
$c =~ s/^\t(call|jbsr|jal) ${T_US}__DISCARD__\n//go;
# MIPS: that may leave some gratuitous asm macros around
# (no harm done; but we get rid of them to be tidier)
......@@ -668,6 +655,7 @@ sub mangle_asm {
while ( $c =~ /${T_MOVE_DIRVS}FUNNY#END#THING/o ) {
$to_move = $1;
if ( $i < ($numchks - 1)
&& ( $to_move =~ /${T_COPY_DIRVS}/
|| ($TargetPlatform =~ /^hppa/ && $to_move =~ /align/ && $chkcat[$i+1] eq 'literal') )) {
......@@ -778,13 +766,9 @@ sub mangle_asm {
$consist =~ s/\//./g;
$consist =~ s/-/_/g;
$consist =~ s/[^A-Za-z0-9_.]/ZZ/g; # ToDo: properly?
print OUTASM $T_HDR_consist, "${consist}${T_POST_LBL}\n";
} elsif ( $TargetPlatform !~ /^(mips|powerpc)-/ ) { # we just don't try in those case (ToDo)
# on mips: consistency string is just a v
# horrible bunch of .bytes,
# which I am too lazy to sort out (WDP 95/05)
print OUTASM $T_HDR_consist, "${consist}${T_POST_LBL}\n"
if $TargetPlatform !~ /^mips-/; # we just don't try in that case
} else {
print STDERR "Couldn't grok consistency: ", $chk[$i];
}
......@@ -870,7 +854,7 @@ sub mangle_asm {
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)-/
|| $TargetPlatform =~ /^(m68k|sparc|i386)-/
) {
print OUTASM $T_HDR_fast;
}
......@@ -910,12 +894,6 @@ sub mangle_asm {
&tidy_up_and_die(1,"$Pgm: unknown chkcat (ghc-asm: $TargetPlatform)\n$chkcat[$i]\n$chk[$i]\n");
}
}
print OUTASM $EXTERN_DECLS if $TargetPlatform =~ /^mips-/;
print OUTASM ".csect .text[PR]\n_section_.text:\n.csect .data[RW]\n\t.long _section_.text\n"
if $TargetPlatform =~ /^powerpc-/;
# 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");
......@@ -1110,12 +1088,7 @@ sub print_doctored {
# final peephole fixes
s/^\tmovl \%eax,36\(\%ebx\)\n\tjmp \*36\(\%ebx\)\n/\tmovl \%eax,36\(\%ebx\)\n\tjmp \*\%eax\n/;
# the short form may tickle perl bug:
# s/^\tmovl \$${T_US}(.*),(\%e[abcd]x)\n\tjmp \*$2/\tjmp $T_US$1/g;
s/^\tmovl \$${T_US}(.*),\%eax\n\tjmp \*\%eax/\tjmp $T_US$1/g;
s/^\tmovl \$${T_US}(.*),\%ebx\n\tjmp \*\%ebx/\tjmp $T_US$1/g;
s/^\tmovl \$${T_US}(.*),\%ecx\n\tjmp \*\%ecx/\tjmp $T_US$1/g;
s/^\tmovl \$${T_US}(.*),\%edx\n\tjmp \*\%edx/\tjmp $T_US$1/g;
s/^\tmovl \$_(.*),(\%e[abcd]x)\n\tjmp \*$2/\tjmp _$1/g;
# Hacks to eliminate some reloads of Hp. Worth about 5% code size.
# We could do much better than this, but at least it catches about
......@@ -1184,8 +1157,6 @@ sub init_FUNNY_THINGS {
"${T_US}_PRMarking_MarkNextGA${T_POST_LBL}", 1,
"${T_US}_PRMarking_MarkNextRoot${T_POST_LBL}", 1,
"${T_US}_PRMarking_MarkNextSpark${T_POST_LBL}", 1,
"${T_US}_PRMarking_MarkNextEvent${T_POST_LBL}", 1,
"${T_US}_PRMarking_MarkNextClosureInFetchBuffer${T_POST_LBL}", 1,
"${T_US}_Scavenge_Forward_Ref${T_POST_LBL}", 1,
"${T_US}__std_entry_error__${T_POST_LBL}", 1,
"${T_US}_startMarkWorld${T_POST_LBL}", 1,
......@@ -1221,7 +1192,7 @@ sub rev_tbl {
for ($i = 0; $i <= $#lines && $lines[$i] !~ /^\t${T_DOT_WORD}\s+/o; $i++) {
$label .= $lines[$i] . "\n",
next if $lines[$i] =~ /^[A-Za-z0-9_]+_info${T_POST_LBL}$/o
|| $lines[$i] =~ /${T_DOT_GLOBAL}/o
|| $lines[$i] =~ /^${T_DOT_GLOBAL}/o
|| $lines[$i] =~ /^${T_US}vtbl_\S+${T_POST_LBL}$/o;
$before .= $lines[$i] . "\n"; # otherwise...
......
......@@ -9,7 +9,7 @@ sub inject_split_markers {
local($hc_file) = @_;
unlink("$Tmp_prefix.unmkd");
local($to_do) = "cp $hc_file $Tmp_prefix.unmkd";
local($to_do) = "$Cp $hc_file $Tmp_prefix.unmkd";
&run_something($to_do, 'Prepare to number split markers');
open(TMPI, "< $Tmp_prefix.unmkd") || &tidy_up_and_die(1,"$Pgm: failed to open `$Tmp_prefix.unmkd' (to read)\n");
......@@ -24,10 +24,14 @@ sub inject_split_markers {
$_ = <TMPI>;
}
print TMPO "__STG_SPLIT_MARKER(1)\n";
print TMPO $_ if ! /\/\* SPLIT \*\//;
print TMPO $_ if ! /^\s*\/\* SPLIT \*\/\s*$/;
# Have to be a bit careful detecting /* SPLIT */ comments
# since a progam may use a string containing "/* SPLIT */"
# We check that there is nothing else on the line
while (<TMPI>) {
if (/\/\* SPLIT \*\//) {
if (/^\s*\/\* SPLIT \*\/\s*$/) {
$marker_no++;
print TMPO "__STG_SPLIT_MARKER($marker_no)\n";
next;
......@@ -54,7 +58,7 @@ sub split_asm_file {
%LocalConstant = (); # we have to subvert C compiler's commoning-up of constants...
$s_stuff = &ReadTMPIUpToAMarker( '' );
$s_stuff = &ReadTMPIUpToAMarker( '', $octr );
# that first stuff is a prologue for all .s outputs
$prologue_stuff = &process_asm_block ( $s_stuff );
# $_ already has some of the next stuff in it...
......@@ -66,14 +70,14 @@ sub split_asm_file {
$prologue_stuff =~ s|"/tmp/ghc\d+\.c"|"$ifile_root\.hc"|g;
while ( $_ ne '' ) { # not EOF
$octr++;
# grab and de-mangle a section of the .s file...
$s_stuff = &ReadTMPIUpToAMarker ( $_ );
$s_stuff = &ReadTMPIUpToAMarker ( $_, $octr );
$this_piece = &process_asm_block ( $s_stuff );
# output to a file of its own
# open a new output file...
$octr++;
$ofname = "${Tmp_prefix}__${octr}.s";
open(OUTF, "> $ofname") || die "$Pgm: can't open output file: $ofname\n";
......@@ -124,7 +128,7 @@ sub collectExports_mips { # Note: MIPS only
}
sub ReadTMPIUpToAMarker {
local($str) = @_; # already read bits
local($str, $count) = @_; # already read bits
for ( $_ = <TMPI>; $_ ne '' && ! /_?__stg_split_marker/; $_ = <TMPI> ) {
......@@ -154,7 +158,7 @@ sub ReadTMPIUpToAMarker {
$_ = <TMPI>;
}
print STDERR "### BLOCK:\n$str" if $Dump_asm_splitting_info;
print STDERR "### BLOCK:$count:\n$str" if $Dump_asm_splitting_info;
# return str
$str;
......@@ -187,15 +191,15 @@ sub process_asm_block_sparc {
if ( $OptimiseC ) {
$str =~ s/_?__stg_split_marker.*:\n//;
} else {
$str =~ s/(\.text\n\t\.align .\n)\t\.global\s+.*_?__stg_split_marker.*\n\t\.proc.*\n/\1/;
$str =~ s/(\t\.align .\n)\t\.global\s+.*_?__stg_split_marker.*\n\t\.proc.*\n/\1/;
$str =~ s/(\.text\n\t\.align .\n)\t\.global\s+.*_?__stg_split_marker.*\n\t\.proc.*\n/$1/;
$str =~ s/(\t\.align .\n)\t\.global\s+.*_?__stg_split_marker.*\n\t\.proc.*\n/$1/;
}
# make sure the *.hc filename gets saved; not just ghc*.c (temp name)
$str =~ s/^\.stabs "(ghc\d+\.c)"/.stabs "$ifile_root.hc"/g; # HACK HACK
# remove/record any literal constants defined here
while ( $str =~ /(\t\.align .\n(LC\d+):\n\t\.ascii.*\n)/ ) {
while ( $str =~ /(\t\.align .\n(LC\d+):\n(\t\.ascii.*\n)+)/ ) {
local($label) = $2;
local($body) = $1;
......@@ -204,7 +208,7 @@ sub process_asm_block_sparc {
$LocalConstant{$label} = $body;
$str =~ s/\t\.align .\nLC\d+:\n\t\.ascii.*\n//;
$str =~ s/\t\.align .\nLC\d+:\n(\t\.ascii.*\n)+//;
}
# inject definitions for any local constants now used herein
......@@ -222,10 +226,10 @@ sub process_asm_block_sparc {
sub process_asm_block_m68k {
local($str) = @_;
# strip the marker (ToDo: something special for unregisterized???)
# strip the marker
$str =~ s/(\.text\n\t\.even\n)\t\.globl\s+.*_?__stg_split_marker.*\n/\1/;
$str =~ s/(\t\.even\n)\t\.globl\s+.*_?__stg_split_marker.*\n/\1/;
$str =~ s/(\.text\n\t\.even\n)\t\.globl\s+.*_?__stg_split_marker.*\n/$1/;
$str =~ s/(\t\.even\n)\t\.globl\s+.*_?__stg_split_marker.*\n/$1/;
# it seems prudent to stick on one of these:
$str = "\.text\n\t.even\n" . $str;
......@@ -262,7 +266,7 @@ sub process_asm_block_alpha {
if ( $OptimiseC ) {
$str =~ s/_?__stg_split_marker.*:\n//;
} else {
$str =~ s/(\t\.align .\n)\t\.globl\s+.*_?__stg_split_marker.*\n\t\.ent.*\n/\1/;
$str =~ s/(\t\.align .\n)\t\.globl\s+.*_?__stg_split_marker.*\n\t\.ent.*\n/$1/;
}
# remove/record any literal constants defined here
......@@ -288,7 +292,7 @@ sub process_asm_block_alpha {
# Slide the dummy direct return code into the vtbl .ent/.end block,
# to keep the label fixed if it's the last thing in a module, and
# to avoid having any anonymous text that the linker will complain about
$str =~ s/(\t\.end [A-Za-z0-9_]+)\n\t# nop/\tnop\n\1/g;
$str =~ s/(\t\.end [A-Za-z0-9_]+)\n\t# nop/\tnop\n$1/g;
print STDERR "### STRIPPED BLOCK (alpha):\n$str" if $Dump_asm_splitting_info;
......@@ -298,10 +302,10 @@ sub process_asm_block_alpha {
sub process_asm_block_iX86 {
local($str) = @_;
# strip the marker (ToDo: something special for unregisterized???)
# strip the marker
$str =~ s/(\.text\n\t\.align .(,0x90)?\n)\.globl\s+.*_?__stg_split_marker.*\n/\1/;
$str =~ s/(\t\.align .(,0x90)?\n)\.globl\s+.*_?__stg_split_marker.*\n/\1/;
$str =~ s/(\.text\n\t\.align .(,0x90)?\n)\.globl\s+.*_?__stg_split_marker.*\n/$1/;
$str =~ s/(\t\.align .(,0x90)?\n)\.globl\s+.*_?__stg_split_marker.*\n/$1/;
# it seems prudent to stick on one of these:
$str = "\.text\n\t.align 4\n" . $str;
......@@ -392,7 +396,7 @@ sub process_asm_block_mips {
if ( $OptimiseC ) {
$str =~ s/_?__stg_split_marker.*:\n//;
} else {
$str =~ s/(\t\.align .\n)\t\.globl\s+.*_?__stg_split_marker.*\n\t\.ent.*\n/\1/;
$str =~ s/(\t\.align .\n)\t\.globl\s+.*_?__stg_split_marker.*\n\t\.ent.*\n/$1/;
}
# remove/record any literal constants defined here
......@@ -418,7 +422,7 @@ sub process_asm_block_mips {
# Slide the dummy direct return code into the vtbl .ent/.end block,
# to keep the label fixed if it's the last thing in a module, and
# to avoid having any anonymous text that the linker will complain about
$str =~ s/(\t\.end [A-Za-z0-9_]+)\n\t# nop/\tnop\n\1/g;
$str =~ s/(\t\.end [A-Za-z0-9_]+)\n\t# nop/\tnop\n$1/g;
$str .= $UNDEFINED_FUNS; # pin on gratuitiously-large amount of info
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment