---snip---
The ELF spec at http://www.sco.com/developers/gabi/ says, "In each
symbol table, all symbols with STB_LOCAL binding precede the weak and
global symbols," and that sh_info is the index of the first non-local
symbol.
I was mixing local and global symbols and setting sh_info to zero. I
also forgot to set the type of the .shstrtab section.
---snip---
Convert each ack.out symbol to ELF, preserving its name and value, and
some but not all other symbol info. The ELF symbol table comes with
ELF section headers. If the input file has no symbols (ack -Rled-s),
then the output file has no ELF section headers.
Append the symbol table and section headers to the ELF file. Linux
ignores this appended info when it execs the file. The info might
pollute the last page of the ELF segment, but Linux clears this
pollution. Tools like nm and gdb can read the ELF symbol table.
I include code to translate debugger symbols to an ELF .stab section.
I did not test this code, because I did not find a platform that can
put S_STB symbols in the ack.out file.
Put end of sentence at end of line. This is roff(7) syntax so the
formatter can make spacing between sentences.
Use the macro .PP to break paragraphs. Use bold for the command name
in SYNOPSIS, to match other ack manuals.
No change to linuxppc and qemuppc. They continue to run ego without
any descr file.
I copied m68020.descr to powerpc.descr and changed some numbers. My
numbers are guesses; I know little about PowerPC cycle counts, and
almost nothing about ego. This powerpc.descr causes most of the
example programs to shrink in size (without descr -> with descr):
65429 -> 57237 hilo_b.osxppc -8192
36516 -> 32420 hilo_c.osxppc -4096
55782 -> 51686 hilo_mod.osxppc -4096
20096 -> 20096 hilo_p.osxppc 0
8813 -> 8813 mandelbrot_c.osxppc 0
93355 -> 89259 paranoia_c.osxppc -4096
92751 -> 84559 startrek_c.osxppc -8192
(Each file has 2 Mach segments, then a symbol table. Each segment
takes a multiple of 4096 bytes. When the code shrinks, we lose a
multiple of 4096 bytes.)
I used "ack -mosxppc -O6 -c.so" to examine the assembly code for
hilo.mod and mandelbrot.c, both without and with descr. This reveals
optimizations made only with descr, from 2 ego phases: SP (stack
pollution) and RA (register allocation). In hilo.mod, SP deletes some
instructions that remove items from the stack. These items get
removed when the function returns. In both hilo.mod and mandelbrot.c,
RA moves some values into local variables, so ncg can make them into
register variables. This shrinks code size, probably because register
variables get preserved across function calls. More values stay in
registers, and ncg emits shorter code.
I believe that the ego descr file uses (time,space) tuples but the ncg
table uses (space,time) tuples. This is confusing. Perhaps I am
wrong, and some or all tuples are backwards. My time values are the
cycle counts in latency from the MPC7450 Reference Manual (but not
including complications like "store serialization").
In powerpc.descr, I give the cost for saving and restoring registers
as if I was using chains of stw and lwz instructions. Actually ncg
uses single stmw and lmw instructions with at least 2 instructions.
The (time,space) for stmw and lmw would be much less than the
(time,space) for chains of stw and lwz. But this ignores the pipeline
of the MPC7450. The chains of stw and lwz may run faster than stmw
and lmw in the pipeline, because the throughput may be better than the
latency. By using the wrong values for (time,space), I'm trying to
tell ego that stmw and lmw are not better than chains of stw and lwz.
This brings in David Given's PowerPC changes, including the addition
of the modern code generator (mcg) for PowerPC.
Resolve minor conflicts in top build.lua and util/led/main.c
This uses uint32_t for the base, file offset, and alignment of each
section, to be consistent with the usage of uint32_t in h/out.h
Also declare setbit() as static.
corresponding invocation in the ncg table so the same helpers can be used for
both mcg and ncg. Add a new IR opcode, FARJUMP, which jumps to a helper
function but saves volatile registers.
unlink("core") doesn't work with OpenBSD, where core dumps have names
like "ncg.core". Users who don't want core dumps can turn them off
with "ulimit -c 0" in sh(1). Then the system doesn't write a core
dump. That's better than writing core then unlinking it.
This commit changes how ack(1) parses backslashes in its descr files.
Before this commit, ack set the high bit of each character escaped by
a backslash, and later cleared all high bits in command arguments, but
this lost the high bits in non-ASCII filenames. After this commit,
ack keeps backslashes in strings while processing them. Functions
scanvars(), scanexpr(), doassign(), unravel(), addargs() now
understand backslashes. I remove from ack_basename() the warning
about non-ASCII characters.
This commit makes some incompatible changes for backslashes in descr
files. None of our descr files uses backslashes, except for those
backslashes that continue lines, and there are no changes for those
backslashes. The problem with non-ASCII filenames had its cause in a
feature that we weren't using.
With this commit, ack now understands backslashes after the = sign in
both "var NAME=value" and "mapflag -flag NAME=value". Before, ack
never scanned backslashes in "var" lines, so "var A=\{B}" failed to
prevent expansion of B. Now it does. Before, ack did scan for
backslashes in the "-flag NAME=" part of "mapflag" lines. Now it
doesn't, so it is no longer possible to map a flag that contains a
literal space, tab, or star "*".
I removed the expansion of "{{" to "{". One can use "\{" for a
literal "{", and "\{" now works in "var" lines. Before and now, ack
never expanded "{" in flags for "mapflag", so the correct way to map a
literal flag "-{" remains "mapflag -{ ...", not "mapflag -{{ ...".
(The other way "mapflag -\{ ..." stops working with this commit.)
Backslashes in strange places, like "{NA\ME}", probably have different
behavior now.
Backslashes in "program" lines now work. Before, ack scanned for
backslashes there but forgot to clear the high bits later.
Escaping < or > as \< or \> now works, and prevents substitution of
the input or output file paths. Before, ack only expanded the first <
or > in each argument. Now, it expands every unescaped < or > in an
argument, but this is an accident of how I rewrote the code. I don't
suggest to put more than one each of < or > in a command. The code no
longer optimizes away its recursive calls when the argument is "<".
The code continues to set or clear the high bit NO_SCAN on the first
characters of flags. This doesn't seem to be a problem, because flags
usually begin with an ASCII hyphen '-'.
If fork() fails, then report a fatal error. Don't spin the cpu
retrying fork() until it succeeds. It can fail when we reach a limit
on the number of processes. Spinning on the cpu would slow down other
processes when we want them to exit. This would get bad if we had a
parallel build with multiple ack processes spinning.
new= newvar(name) takes ownership of the string and might free its
memory. Don't print name. Do print new->v_name.
Also #include <string.h> for strcmp().
Declare most functions before using them. I declare some functions in
ack.h and some in trans.h (because trans.h declares type trf). I
leave declarations of scanb() and scanvars() in .c files because they
need type growstring. (I can't #include "grows.h" in another header
file as long as grows.h doesn't guard against multiple inclusion.)
Functions used within one file become static. I remove a few tiny
functions. I move a few functions or declarations to more convenient
places. Some functions now return void instead of a garbage int.
I feel that keyword "register" is obsolete, so I removed it from where
I was editing. This commit doesn't touch mktables.c
register 'type'; now use int/float/long/double throughout to identify
registers. Lots of register allocator tweaks and table bugfixes --- we now get
through the dreading Mathlib.mod!