Commit graph

1724 commits

Author SHA1 Message Date
George Koehler 85fcbde22f Check LOI expressions to prevent a read after free.
CS eliminates outer expressions before inner ones, as `x * y * z`
before `x * y`.  It does this by reversing the order of expressions in
the code.  This almost always works, but it sometimes doesn't work if
a STI changes the value number of a LOI.  In code like `expr1 LOI
expr2 STI expr2 LOI`, CS might eliminate the inner `expr2` before the
outer `expr2 LOI`.  This caused a read after free because the
occurrence of `expr2 LOI` pointed to the eliminated lines of `expr2`.

This bug went unnoticed until my recent changes caused CS to crash
with a double free.  I did not get the crash in OpenBSD, but I saw the
crash in Travis, then David Given reproduced the crash in Linux.  See
the discussion in https://github.com/davidgiven/ack/pull/73
2018-03-12 20:58:31 -04:00
George Koehler ebba76e08f Don't read INSTR(l) after oldline(l) frees it.
This bug got in my way while I was looking for another read-after-free
bug in the CS phase.
2018-03-11 20:10:13 -04:00
George Koehler 12643f1740 Solve some gcc warnings in ego.
Some of these are from gcc -Wimplicit
2018-03-08 18:51:07 -05:00
George Koehler b1b737ed6c Optimize procedures that do both a / b and a % b.
Enable this in CS for PowerPC; disable it for all other machines.
PowerPC has no remainder instruction; the back end uses division to
compute remainder.  If CS finds both a / b and a % b, then CS now
rewrites a % b as a - b * (a / b) and computes a / b only once.  This
removes an extra division in the PowerPC code, so it saves both time
and space.

I have not considered whether to enable this optimization for other
machines.  It might be less useful in machines with a remainder
instruction.  Also, if a % b occurs before a / b, the EM code gets a
DUP.  PowerPC ncg handles this DUP well; other back ends might not.
2018-03-05 13:32:06 -05:00
George Koehler f26259caac Check AAR earlier to prevent LOI/STI unknown size.
In ego, the CS phase may convert a LAR/SAR to AAR LOI/STI so it can
optimize multiple occurrences of AAR of the same array element.  This
conversion should not happen if it would LOI/STI a large or unknown
size.

cs_profit.c okay_lines() checked the size of each occurrence of AAR
except the first.  If the first AAR was the implicit AAR in a LAR/SAR,
then the conversion happened without checking the size.  For unknown
size, this made a bad LOI -1 or STI -1.  Fix by checking the size
earlier: if a LAR/SAR has a bad size, then don't enter it as an AAR.

This Modula-2 code showed the bug.  Given M.def:

    DEFINITION MODULE M;
    TYPE S = SET OF [0..95];
    PROCEDURE F(a: ARRAY OF S; i, j: INTEGER);
    END M.

and M.mod:

    (*$R-*) IMPLEMENTATION MODULE M;
    FROM SYSTEM IMPORT ADDRESS, ADR;
    PROCEDURE G(s: S; p, q: ADDRESS; t: S); BEGIN
      s := s; p := p; q := q; t := t;
    END G;
    PROCEDURE F(a: ARRAY OF S; i, j: INTEGER); BEGIN
      G(a[i + j], ADR(a[i + j]), ADR(a[i + j]), a[i + j])
    END F;
    END M.

then the bug caused an error:

    $ ack -mlinuxppc -O3 -c.e M.mod
    /tmp/Ack_b357d.g, line 57: Argument range error

The bug had put LOI -1 in the code, then em_decode got an error
because -1 is out of range for LOI.

Procedure F has 4 occurrences of `a[i + j]`.  The size of `a[i + j]`
is 96 bits, or 12 bytes, but the EM code hides the size in an array
descriptor, so the size is unknown to CS.  The pragma `(*$R-*)`
disables a range check on `i + j` so CS can work.  EM uses AAR for the
2 `ADR(a[i + j])` and LAR for the other 2 `a[i + j]`.  EM pushes the
arguments to G in reverse order, so the last `a[i + j]` in Modula-2 is
the first LAR in EM.

CS found 4 occurrences of AAR.  The first AAR was an implicit AAR in
LAR.  Because of the bug, CS converted this LAR 4 to AAR 4 LOI -1.
2018-03-02 16:06:21 -05:00
George Koehler a7bb4ec4b1 Fixes for compiling ego with -DTRACE
- In share/debug.c, undo my mistake in commit 9037d13 by changing
   vfprintf back to fprintf in OUTTRACE.

 - In ud/ud.c, move the trace output from stdout to stderr, because
   stdout has ego's output file, which becomes opt2's input file.  If
   trace output goes to stdout, it gets prepended to the output file,
   and opt2 errors with "wrong input file".

I also edit both build.lua files so ego depends on its header files;
this part isn't needed for -DTRACE.

One can now use -DTRACE by adding it to the cflags in both build.lua
files.
2018-03-01 13:19:38 -05:00
George Koehler 0a6d3de7fe Use prototypes in ego/cs, ego/sp. 2018-02-05 16:09:30 -05:00
George Koehler 88207db638 Use <stdarg.h> in util/misc/convert.c
I made a syntax error in some .e file, and em_encode dumped core
because a 64-bit pointer didn't fit in a 32-bit int.  Now use stdarg
to pass pointers to error() and fatal().

Stop using the number of errors as the exit status.  Many systems use
only the low 8 bits of the exit status, so 256 errors would become 0.

Also change modules/src/print to accept const char *buf
2017-12-06 17:09:12 -05:00
David Given 6d91bdbbbd
Merge pull request #69 from kernigh/kernigh-stdc
use libc assert, strcmp; declare more functions; fewer clang warnings
2017-11-19 12:00:40 +01:00
George Koehler 11d48be49e Fix my typo from commit 5bbbaf4. 2017-11-17 15:46:24 -05:00
George Koehler d99a0682fc Switch ego to libc <assert.h>
I also tried, in types.h, to switch ego to libc <stdbool.h>, but that
causes an infinite loop in the IL phase.
2017-11-15 19:48:53 -05:00
George Koehler 9037d137f5 Add prototypes, void in util/ego/share
This uncovers a problem in il/il_aux.c: it passes 3 arguments to
getlines(), but the function expects 4 arguments.  I add FALSE as the
4th argument.  TRUE would fill in the list of mesregs.  IL uses
mesregs during phase 1, but this call to getlines() is in phase 2.
TRUE would leak memory unless I added a call to Ldeleteset(mesregs).
So I pass FALSE.

Functions passed to go() now have a `void *` parameter because
no_action() now takes a `void *`.
2017-11-15 17:19:56 -05:00
David Given caa9df5449 LLgen won't update the output file timestamp if the file contents doesn't
change, which confuses ninja no end. Fix this.

Fixes: #68
2017-11-15 19:41:39 +01:00
George Koehler 5bbbaf4919 Use size_t and void with memory allocation in ego.
alloc.h now needs to #include <stdlib.h> to find type size_t and
function free().
2017-11-14 20:35:18 -05:00
George Koehler 87a2315037 strcmp, strncmp are in <string.h>
*Important:*  Do `make clean` to work around a problem and prevent
infinite rebuilds, https://github.com/davidgiven/ack/issues/68

I edit tokens.g in util/LLgen/src, so I regenerate tokens.c.  The
regeneration script bootstrap.sh can't find LLgen, but I can run the
same command by typing the path to llgen.
2017-11-14 17:35:35 -05:00
George Koehler fbff3a4790 Check each format string in tabgen.c
Silence warning from clang at `if (ch2 = ...)`

Delete `|| rm %{outs}` in build.lua, because it hid the exit status of
tabgen, so if tabgen failed, the build continued and failed later.
2017-11-13 20:59:03 -05:00
George Koehler ca4bd38206 Delete old "assert.h" files; use libc <assert.h>.
Edit build.lua for programs losing their private assert.h, so they
depend on a list of .h files excluding assert.h.

Remove modules/src/assert; it would be a dependency of cpp.ansi but we
didn't build it, so cpp.ansi uses the libc assert.

I hope that libc <assert.h> can better report failed assertions.  Some
old "assert.h" files didn't report the expression.  Some reported a
literal "x", because traditional C expanded the macro parameter x in
"x", but ANSI C89 doesn't expand macro parameters in string literals.
2017-11-09 22:22:13 -05:00
George Koehler 0fc0faef08 Restore an assignment deleted in commit 789f79b.
Because of the accidental deletion, mcgg on my machine followed a
garbage pointer, and never wrote calls to emit_fragment.

A wrong call to `data->emit_reg(0, 0)` instead of the correct
`data->emit_fragment(0)` caused PowerPC mcg to emit an empty string
instead of `8(fp)`, causing a syntax error in PowerPC as.

The wrong `data->emit_reg(0, 0)` called the function emit_reg() in
mach/proto/mcg/pass_instructionselection.c, but that function
unfortunately has `if (vreg) { ... }`.  The call had vreg == NULL
because the fragment wasn't a vreg, but emit_reg() ignored the problem
and emit nothing.
2017-11-07 23:52:52 -05:00
George Koehler 50a7031007 Don't use '-' in option string to getopt().
@dram reported a build failure in FreeBSD at
https://github.com/davidgiven/ack/issues/1#issuecomment-273668299

Linux manual for getopt(3) says:
> If the first character of optstring is '-', then each nonoption
> argv-element is handled as if it were the argument of an option with
> character code 1....
>
> The use of '+' and '-' in optstring is a GNU extension.

GNU/Linux and OpenBSD handle '-' in this special way, but FreeBSD
seems not to.  If '-' is not special, then em_ego can't find its input
file, so the build must fail.  This commit stops using '-' in both
em_b and em_ego, but doesn't change mcg.

Also fix em_ego -O3 to not act like -O4.
2017-10-29 23:25:07 -04:00
George Koehler 3d6ee435cf Fix pattern that was rewriting func(! var, var) as func(1).
Bug reported by Rune, see
 - https://sourceforge.net/p/tack/mailman/message/35809953/
 - https://github.com/davidgiven/ack/issues/62

In EM code, beq and bne pop 2 values and compare them, but teq and tne
pop only 1 value and compare it with zero.  We need cms to compare 2
values; other patterns may convert cmi or cmu to cms.
2017-10-29 14:53:33 -04:00
George Koehler cb8b28c088 For DIAGOPT, change outshort(patno) to outshort(lino - 1).
This is more useful when looking for patterns; lino - 1 is probably
the line number in the patterns file.  DIAGOPT is off by default but
one can edit optim.h to enable it.

The other changes just clean up whitespace.
2017-10-29 14:18:47 -04:00
George Koehler c567532eee mktab depends on some of the *.h files.
If I edit optim.h to #define DIAGOPT then mktab must get rebuilt.
2017-10-28 21:41:59 -04:00
George Koehler c261e2efaf Add .pas as a Pascal suffix.
Requested by @dram in https://github.com/davidgiven/ack/issues/41
2017-10-28 11:59:35 -04:00
George Koehler 2a92f9bf4d Add a few more error checks and adjustments to reglap.
In util/ncgg, add two more errors for tables using reglap:
 - "Two sizes of reg_float can't be same size"
 - "Missing reg_float of size %d to contain %s"

In mach/proto/ncg, rename macro isregvar_size() to PICK_REGVAR(), so
the macro doesn't look like a function.  This macro sometimes doesn't
evaluate its second argument.

In mach/powerpc/ncg/mach.c, change type of lfs_set to uint32_t, and
change the left shifts from 1U<<regno to (uint32_t)1<<regno, because
1U would be too small for machines with 16-bit int.
2017-10-18 22:00:12 -04:00
George Koehler 73ad5a227d Rename RELOLIS to RELOPPC_LIS.
This relocation is specific to PowerPC.  @davidgiven suggested the
name RELOPPC_LIS in
https://github.com/davidgiven/ack/pull/52#issuecomment-279856501

Reindent the list in h/out.h and util/led/ack.out.5 because
RELOLIS_PPC is a long name.  I use spaces and no tabs because the tabs
looked bad in the manual page.
2017-10-18 15:39:31 -04:00
George Koehler 307a8b996e Add regvar_w() and regvar_d() for use with reglap.
If the ncg table uses reglap, then regvar($1, reg_float) would have
two sizes of registers.  An error from ncgg would happen if regvar()
was in a token that allows only one size.  Now one can pick a size
with regvar_w() for word size or regvar_d() for double-word size.

Add regvar_d and regvar_w as keywords in ncgg.  Modify EX_REGVAR to
include the register size.  In ncg, add some checks for the register
size.  In tables without reglap, regvar() works as before, and ncg
ignores the register size in EX_REGVAR.
2017-10-17 12:05:41 -04:00
George Koehler d6e9eac785 Merge branch 'default' into kernigh-linuxppc
This merges several fixes and improvements from upstream.  This
includes commit 5f6a773 to turn off qemuppc.  I see several failing
tests from qemuppc; this merge will hide the test failures.
2017-10-14 13:50:49 -04:00
George Koehler 7e9348169c Add reglap to ncg. Add 4-byte reg_float to PowerPC ncg.
The new feature "reglap" allows two sizes of floating-point register
variables (reg_float), if each register overlaps a single register of
the other size.  PowerPC ncg uses reglap to define 4-byte instances
of f14 to f31 that overlap the 8-byte instances.

When ncgg sees the definition of fs14("f14")=f14, it removes the
8-byte f14 from its rvnumbers array, and adds the 4-byte fs14 in its
place.  Later, when ncg puts a variable in fs14, if it is an 8-byte
variable, then ncg switches to the 8-byte f14.  The code has
/* reglap */ comments in util/ncgg or #ifdef REGLAP in mach/proto/ncg

reglap became necessary because my commit a20b87c caused PowerPC ego
to allocate reg_float in both 4-byte and 8-byte sizes.
2017-10-14 12:40:04 -04:00
David Given b83173734d More ansification. 2017-08-06 15:57:49 +02:00
David Given 1203e8afd2 mkstemp() is a bit more complex than it looks; because ego wants to use the
same base name and generate multiple files based on it, we can't really use
mkstemp() for every temporary file. Instead, use mkstemp() once on a
placeholder, then generate temporary names based on this. (And delete the
placeholder once we've finished.)
2017-08-06 14:25:12 +02:00
David Given 64f2fa9d46 Stop using mktemp() --- on Haiku, it always generates the same filenames,
pretty much guaranteeing temporary file overwrites on parallel builds. Use
mkstemp() instead which creates the files atomically.
2017-08-06 13:22:05 +02:00
David Given 789f79b369 Ansification, warning fixes, C89ification. 2017-08-06 12:42:17 +02:00
David Given 60e7d06d82 Ansification and warning fixes. 2017-08-06 11:58:36 +02:00
David Given fd10cf7ac2 Merge from trunk. 2017-08-06 10:42:16 +02:00
George Koehler a20b87ca01 In ego, put both words and double-words in reg_float.
The size of a reg_float isn't in the descr file, so ego doesn't know.
PowerPC and SPARC are the only arches with floating-point registers in
their descr files.  PowerPC and SPARC registers can hold both 4-byte
and 8-byte floats, so I want ego to do both sizes.

This might break our SPARC code expander because ego doesn't know that
8-byte values take 2 registers in SPARC.  (So ego might allocate too
many registers and deallocate too much stack space.)  We don't build
the SPARC code expander, and its descr file is already wrong: its list
of register save costs is too short, so ego will read past the end of
the array.

This commit doesn't fix the problem with ego and PowerPC ncg.  Right
now, ncg refuses to put 4-byte floats in registers, but ego expects
them to get registers and deallocates their stack space.  So ncg emits
programs that use the deallocated space, and the values of 4-byte
floats become corrupt.
2017-02-16 19:55:52 -05:00
George Koehler cbe5d8640b Add floating-point register variables to PowerPC ncg.
Use f14 to f31 as register variables for 8-byte double-precison.
There are no regvars for 4-byte double precision, because all
regvar(reg_float) must have the same size.  I expect more programs to
prefer 8-byte double precision.

Teach mach/powerpc/ncg/mach.c to emit stfd and lfd instructions to
save and restore 8-byte regvars.  Delay emitting the function prolog
until f_regsave(), so we can use one addi to make stack space for both
local vars and saved registers.  Be more careful with types in mach.c;
don't assume that int and long and full are the same.

In ncg table, add f14 to f31 as register variables, and some rules to
use them.  Add rules to put the result of fadd, fsub, fmul, fdiv, fneg
in a regvar.  Without such rules, the result would go in a scratch
FREG, and we would need fmr to move it to the regvar.  Also add a rule
for pat sdl inreg($1)==reg_float with STACK, so we can unstack the
value directly into the regvar, again without a scratch FREG and fmr.

Edit util/ego/descr/powerpc.descr to tell ego about the new float
regvars.  This might not be working right; ego usually decides against
using any float regvars, so ack -O1 (not running ego) uses the
regvars, but ack -O4 (running ego) doesn't use the regvars.

Beware that ack -mosxppc runs ego using powerpc.descr but -mlinuxppc
and -mqemuppc run ego without a config file (since 8ef7c31).  I am
testing powerpc.descr with a local edit to plat/linuxppc/descr to run
ego with powerpc.descr there, but I did not commit my local edit.
2017-02-15 19:34:07 -05:00
George Koehler 13beb5e336 Document RELOLIS from commit 1bf58cf.
I hastily chose the name RELOLIS for this relocation type.  If we want
to rename it, we only need to edit these files:

 - h/out.h
 - mach/powerpc/as/mach5.c
 - util/amisc/ashow.c
 - util/led/ack.out.5
 - util/led/relocate.c
2017-02-10 11:59:34 -05:00
George Koehler 1bf58cf51c Add RELOLIS for PowerPC lis with ha16 or hi16.
The new relocation type RELOLIS handles these instructions:

    lis RT, ha16[expr] == addis RT, r0, ha16[expr]
    lis RT, hi16[expr] == addis RT, r0, hi16[expr]

RELOLIS stores a 32-bit value in the program text.  In this value, the
high bit is a ha16 flag, the next 5 bits are the target register RT,
and the low bits are a signed 26-bit offset.  The linker replaces this
value with the lis instruction.

The old RELOPPC relocated a ha16/lo16 or hi16/lo16 pair.  The new
RELOLIS relocates only a ha16 or hi16, so it is no longer necessary to
have a matching lo16 in the next instruction.  The disadvantage is
that RELOLIS has only a signed 26-bit offset, not a 32-bit offset.

Switch the assembler to use RELOLIS for ha16 or hi16 and RELO2 for
lo16.  The li32 instruction still uses the old RELOPPC relocation.

This is not the same as my RELOPPC change from my recent mail to
tack-devel (https://sourceforge.net/p/tack/mailman/message/35651528/).
This commit is on a different branch.  Here I am throwing away my
RELOPPC change and instead trying RELOLIS.
2017-02-08 11:46:31 -05:00
George Koehler a41b6f0458 Allow more PowerPC instructions in relocations.
I need this for relocations in lis/lfd pairs.  I add lfd along with
addi, lfs, lha, stfs, stfd to the list.
2017-01-23 16:19:38 -05:00
George Koehler f91bc2804d Tune the installed manual pages.
This commit slightly improves the formatting of the manuals.  My
OpenBSD machine uses mandoc(1) to format manuals.  I check the manuals
with `mandoc -T lint` and fix most of the warnings.  I also make
other changes where mandoc didn't warn me.

roff(7) says, "Each sentence should terminate at the end of an input
line," but we often forgot this rule.  I insert some newlines after
sentences that had ended mid-line.

roff(7) also says that blank lines "are only permitted within literal
contexts."  I delete blank lines.  This removes some extra blank lines
from mandoc's output.  If I do want a blank line in the output, I call
".sp 1" to make it in man(7).  If I want a blank line in the source,
but not the output, I put a plain dot "." so roff ignores it.

Hyphens used for command-line options, like \-a, should be escaped by
a backslash.  I insert a few missing backslashes.

mandoc warns if the date in .TH doesn't look like a date.  Our manuals
had a missing date or the RCS keyword "$Revision$".  Git doesn't
expand RCS keywords.  I put in today's date, 2017-01-18.

Some manuals used tab characters in filled mode.  That doesn't work.
I use .nf to turn off filled mode, or I use .IP in man(7) to make the
indentation without a tab character.

ack(1) defined a macro .SB but never used it, so I delete the
definition.  I also remove a call to the missing macro .RF.

mandoc warns about empty paragraphs.  I deleted them.  mandoc also
warned about these macro pairs in anm(1):

    .SM
    .B text

The .SM did nothing because the .B text is on a different line.  I
changed each pair to .SB for small bold text.

I make a few other small changes.
2017-01-18 23:02:30 -05:00
David Given 1a5c595a12 Merge pull request #45 from davidgiven/dtrg-fixups
Add hi16[], ha16[], lo16[] support to the PowerPC assembler
2017-01-18 20:18:04 +01:00
David Given d5a83fd73e Clean up the led includes. 2017-01-18 19:55:56 +01:00
David Given 01a61e0708 Apply kernigh@'s fix to broken symbol tables in aelflod (via mailing list patch):
---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---
2017-01-18 00:06:14 +01:00
David Given b63a4513d5 Add missing header. 2017-01-15 12:04:47 +01:00
David Given 9a346c382d Turns out Apple's hi16/ha16 exactly match my ha16/has16, so renamed
accordingly. (Memo to self: read the docs *before* doing the work.)
2017-01-15 11:59:33 +01:00
David Given f80acfe9f5 Signed vs unsigned lower halves of powerpc fixups are now handled by having two
assembler directives, ha16() and has16(), for the upper half; has16() applies
the sign adjustment. .powerpcfixup is now gone, as we generate the relocation
in ha*() instead. Add special logic to the linker for undoing and redoing the
sign adjustment when reading/writing fixups. Tests still pass.
2017-01-15 11:51:37 +01:00
David Given 14aab21204 Revert change; addis/ori requires different handling to addis/lwz due to ori's
payload being unsigned while lwz's payload is signed.
2017-01-15 10:31:20 +01:00
David Given 8edbff9795 Add assembler support for fixing up arbitrary oris/addi pairs of instructions;
this should allow oris/lwz constant value loads, which will save an opcode.
2017-01-15 00:15:01 +01:00
David Given 62022c6f6b Don't print source file names during compilation (gcc stopped doing it years
ago).
2017-01-08 00:16:35 +01:00
David Given 4b7fc5e233 Run through clang-format. 2017-01-08 00:15:23 +01:00