%% /usr/local/src/lcc/lcc-4.1.beta.8/TO-DO, Mon Apr  2 17:51:54 2001
%% Edit by Nelson H. F. Beebe <beebe@math.utah.edu>

This file contains time-stamped chronologically-ordered to-do notes
recorded during lcc-4.1.beta.8 development.  It also includes old
unresolved items from earlier 4.1.beta.* releases.

------------------------------------------------------------------------
Thu Mar 15 15:37:06 2001
Can/Should cpp support nonstandard directives, like #lint,
#include_next, et al?

gcc and Sun compilers support a preprocessor extension of the
form documented here (from the gcc-2.95.2 manual):

`-AQUESTION(ANSWER)'
     Assert the answer ANSWER for QUESTION, in case it is tested with a
     preprocessing conditional such as `#if #QUESTION(ANSWER)'.  `-A-'
     disables the standard assertions that normally describe the target
     machine.

For example, on Sun Solaris 2.7 with Sun Workshop 6 update 1 C 5.2
2000/09/11 native compilers, /usr/include/ctype.h has this use:

#if !#lint(on) && !defined(__lint)
...
#endif

------------------------------------------------------------------------
Thu Mar 15 18:14:31 2001
Solve rcc core dump on DEC Alpha, when compiled with cc instead of
	c89:

dbx) where
>  0 stringf(fmt = 0x140025ce8 = "%s") ["../lcc-4.1.beta.6/src/output.c":62, 0x12002289c]
   1 defsymbol2(p = 0x14003e468) ["/usr/tmp/lcc/4.1.beta.6/alpha-osf/sparc.c":5045, 0x1200463dc]
   2 dclglobal(sclass = 67, id = 0x140038187 = "up", ty = 0x14003e420, pos = 0x11fffe8e0) ["../lcc-4.1.beta.6/src/decl.c":241, 0x12001d3b0]
   3 decl(dcl = 0x12001d0e4) ["../lcc-4.1.beta.6/src/decl.c":190, 0x12001d040]
   4 program() ["../lcc-4.1.beta.6/src/decl.c":40, 0x12001c500]
   5 main(argc = 6, argv = 0x11fffe988) ["../lcc-4.1.beta.6/src/main.c":55, 0x12000d814]

(sparc.c is the expansion of src/sparc.md).
(dbx) s
  [stringf:61 ,0x12002287c]     va_start(ap, fmt);
(dbx) n
  [stringf:62 ,0x12002289c]     vfprint(NULL, buf, fmt, ap);
(dbx) p buf
""
(dbx) p fmt
0x140025ce8 = "%s"
(dbx) p ap
struct {
    _a0 = 0x11fffe830
    _offset = 8
}
(dbx) s
  [vfprint:69 ,0x120022918]     for (; *fmt; fmt++)
(dbx) s
  [vfprint:70 ,0x120022924]     if (*fmt == '%')
(dbx) p fmt
0x140025ce8 = "%s"
(dbx) s
  [vfprint:71 ,0x120022934]     switch (*++fmt) {
(dbx) s
  [vfprint:88 ,0x120022b6c]     case 's': bp = outs(va_arg(ap, char *), f, bp); break;
(dbx) s
  [outs:6 ,0x1200224fc]         if (f)
(dbx) p f
(dbx) p f
(nil)
(dbx) n
  [outs:9 ,0x120022528]         while (*bp = *str++)
(dbx) s
signal Segmentation fault at   [outs:9 +0x4,0x12002252c]        while (*bp = *str++)
(dbx) where
>  0 outs(str = (nil), f = (nil), bp = 0x11fffe400 = "^C") ["../lcc-4.1.beta.6/src/output.c":9, 0x12002252c]
   1 vfprint(f = (nil), bp = 0x11fffe400 = "^C", fmt = 0x140025ce9 = "s", ap = struct {
    _a0 = 0x11fffe830
    _offset = 16
}) ["../lcc-4.1.beta.6/src/output.c":88, 0x120022b90]
   2 stringf(fmt = 0x140025ce8 = "%s") ["../lcc-4.1.beta.6/src/output.c":62, 0x1200228b4]
   3 defsymbol2(p = 0x14003e468) ["/usr/tmp/lcc/4.1.beta.6/alpha-osf/sparc.c":5045, 0x1200463dc]
   4 dclglobal(sclass = 67, id = 0x140038187 = "up", ty = 0x14003e420, pos = 0x11fffe8e0) ["../lcc-4.1.beta.6/src/decl.c":241, 0x12001d3b0]
   5 decl(dcl = 0x12001d0e4) ["../lcc-4.1.beta.6/src/decl.c":190, 0x12001d040]
   6 program() ["../lcc-4.1.beta.6/src/decl.c":40, 0x12001c500]
   7 main(argc = 6, argv = 0x11fffe988) ["../lcc-4.1.beta.6/src/main.c":55, 0x12000d814]

Here is the outs() code:

static char *outs(const char *str, FILE *f, char *bp) {
	if (f)
		fputs(str, f);
	else
		while (*bp = *str++)
			bp++;
	return bp;
}

The problem is that it is unexpected that str is NULL, so the code
dereferences a NULL pointer.

When the code is compiled with c89 instead, I get these arguments to
outs():

(dbx) where
>  0 outs(str = 0x140038187 = "up", f = (nil), bp = 0x11fffe380 = "^C") ["../lcc-4.1.beta.6/src/output.c":6, 0x12002220c]
   1 vfprint(f = (nil), bp = 0x11fffe380 = "^C", fmt = 0x140025b59 = "s", ap = struct {
    _a0 = 0x11fffe7b0
    _offset = 16
}) ["../lcc-4.1.beta.6/src/output.c":88, 0x12002289c]
   2 stringf(fmt = 0x140025b58 = "%s") ["../lcc-4.1.beta.6/src/output.c":62, 0x1200225c0]
   3 defsymbol2(p = 0x14003e468) ["/tmp//lcc/4.1.beta.6/alpha-osf/sparc.c":5045, 0x120045ec0]
   4 dclglobal(sclass = 67, id = 0x140038187 = "up", ty = 0x14003e420, pos = 0x11fffe860) ["../lcc-4.1.beta.6/src/decl.c":241, 0x12001d11c]
   5 decl(dcl = 0x12001ce54) ["../lcc-4.1.beta.6/src/decl.c":190, 0x12001cdb0]
   6 program() ["../lcc-4.1.beta.6/src/decl.c":40, 0x12001c270]
   7 main(argc = 8, argv = 0x11fffe908) ["../lcc-4.1.beta.6/src/main.c":55, 0x12000d7f0]

Now str is non-NULL, and rcc runs correctly, and to completion!

The caller of outs is output.c:88:
			case 's': bp = outs(va_arg(ap, char *), f, bp); break;
Thus, the culprit is apparently va_arg()!

Examination of the preprocessor output from cc and c89 shows that the
code in both cases in the call to outs() is identical.

I even extracted skeletons of the functions in the call trace into a
file, argbug.c: it worked fine with both compilers!  At the moment, I
am stumped: a build with cc always fails: -g, -O3, -taso (32-bit
addressing instead of 64-bit addressing) all had no effect.

------------------------------------------------------------------------
Sat Mar 17 09:35:57 2001
There is a minor typo in this message:

% lcc ll.c && ./a.out
ll.c:25: warning: shifting an `long long int' by 63 bits is undefined
			   ^^^ should by `a'
n = 0x0000000080000000

It arises from simp.c:

	% grep -n 'shifting an' `find . -name '*.[ch]' `
	./src/simp.c:452:                               warning("shifting an `%t' by %d bits is undefined\n", ty, r->u.v.i);
	./src/simp.c:461:                               warning("shifting an `%t' by %d bits is undefined\n", ty, r->u.v.i);
	./src/simp.c:547:                               warning("shifting an `%t' by %d bits is undefined\n", ty, r->u.v.i);
	./src/simp.c:556:                               warning("shifting an `%t' by %d bits is undefined\n", ty, r->u.v.i);

The test code is:

/***********************************************************************
[17-Mar-2001]
***********************************************************************/

#include <stdio.h>
#include <stdlib.h>

#if defined(__STDC__) || defined(__cplusplus)
#define ARGS(parenthesized_list) parenthesized_list
#else
#define ARGS(parenthesized_list) ()
#endif

#ifndef EXIT_SUCCESS
#define EXIT_SUCCESS 0
#endif

int	main ARGS((int argc, char* argv[]));

int
main(int argc, char* argv[])
{
    unsigned long long n;

    n = 1L;

    n = (unsigned long long)n << 30L;
    printf("n = 1 << 30 = 0x%016llx\n", n);

    n = (unsigned long long)n << 30L;
    printf("n = 1 << 60 = 0x%016llx\n", n);

    n = (unsigned long long)n << 1L;
    printf("n = 1 << 61 = 0x%016llx\n", n);

    n = (unsigned long long)n << 1L;
    printf("n = 1 << 62 = 0x%016llx\n", n);

    n = (unsigned long long)n << 1L;
    printf("n = 1 << 63 = 0x%016llx\n", n);

    n = (unsigned long long)n << 1L;
    printf("n = 1 << 64 = 0x%016llx\n", n);

    return (EXIT_SUCCESS);
}


------------------------------------------------------------------------
Sat Mar 17 09:43:05 2001
lcc does not support long long ints:  e.g., on SGI system:

% rm -f a.out ; cc ll.c && ./a.out
n = 1 << 30 = 0x0000000040000000
n = 1 << 60 = 0x1000000000000000
n = 1 << 61 = 0x2000000000000000
n = 1 << 62 = 0x4000000000000000
n = 1 << 63 = 0x8000000000000000
n = 1 << 64 = 0x0000000000000000

% rm -f a.out ; gcc ll.c && ./a.out
n = 1 << 30 = 0x0000000040000000
n = 1 << 60 = 0x1000000000000000
n = 1 << 61 = 0x2000000000000000
n = 1 << 62 = 0x4000000000000000
n = 1 << 63 = 0x8000000000000000
n = 1 << 64 = 0x0000000000000000

% rm -f a.out ; lcc ll.c && ./a.out
n = 1 << 30 = 0x7fff2eac7fff2eac
n = 1 << 60 = 0x0000002100000000
n = 1 << 61 = 0x0000002100000000
n = 1 << 62 = 0x0000002100000000
n = 1 << 63 = 0x0000002100000000
n = 1 << 64 = 0x0000002100000000

Also, gcc and cc recognize LL suffixes, but lcc does not.
------------------------------------------------------------------------
Sat Mar 17 13:31:27 2001
In "make check-3" on alpha/osf, get warnings:

	/tmp/build/lcc/4.1.beta.6/alpha/osf/alpha.c:
	/tmp/build/lcc/4.1.beta.6/alpha/osf/alpha.c:4922: warning:
		overflow in converting constant expression from `int'
		to `unsigned int'
	/tmp/build/lcc/4.1.beta.6/alpha/osf/alpha.c:4923: warning:
		overflow in converting constant expression from `int'
		to `unsigned int'

	/tmp/build/lcc/4.1.beta.6/alpha/osf/mips.c:
	/tmp/build/lcc/4.1.beta.6/alpha/osf/mips.c:4031: warning:
		conversion from `pointer to void' to `unsigned int' is
		compiler dependent
	/tmp/build/lcc/4.1.beta.6/alpha/osf/mips.c:4031: warning:
		conversion from `pointer to void' to `unsigned int' is
		undefined

	/tmp/build/lcc/4.1.beta.6/alpha/osf/sparc.c:
	/tmp/build/lcc/4.1.beta.6/alpha/osf/sparc.c:4934: warning:
		conversion from `pointer to void' to `unsigned int' is
		compiler dependent
	/tmp/build/lcc/4.1.beta.6/alpha/osf/sparc.c:4934: warning:
		conversion from `pointer to void' to `unsigned int' is
		undefined

	/tmp/build/lcc/4.1.beta.6/alpha/osf/x86.c:
	/tmp/build/lcc/4.1.beta.6/alpha/osf/x86.c:5644: warning:
		conversion from `pointer to void' to `unsigned int' is
		compiler dependent
	/tmp/build/lcc/4.1.beta.6/alpha/osf/x86.c:5644: warning:
		conversion from `pointer to void' to `unsigned int' is
		undefined

	/tmp/build/lcc/4.1.beta.6/alpha/osf/x86linux.c:
	/tmp/build/lcc/4.1.beta.6/alpha/osf/x86linux.c:6853: warning:
		conversion from `pointer to void' to `int' is compiler
		dependent
	/tmp/build/lcc/4.1.beta.6/alpha/osf/x86linux.c:6853: warning:
		conversion from `pointer to void' to `int' is
		undefined
------------------------------------------------------------------------
Sat Mar 17 19:03:37 2001
Currently have these *.c files in etc:

	alpha-linux.c
	alpha-osf.c
	bprint.c
	gcc-solaris.c
	lcc.c
	mips-irix.c
	ops.c
	parisc-hpux.c
	ppc-aix.c
	ppc-linux.c
	ppc-macosx.c
	sparc-linux.c
	sparc-solaris.c
	x86-freebsd.c
	x86-linux.c
	x86-win32.c

It would be consistent with the directory structure elsewhere to
change those hyphens to slashes!

[DONE: Mon Mar 19 13:35:35 2001.  The etc directory structure now
	looks like this:

		etc/alpha/linux.c
		etc/alpha/osf.c
		etc/bprint.c
		etc/lcc.c
		etc/mips/irix.c
		etc/ops.c
		etc/parisc/hpux.c
		etc/ppc/aix.c
		etc/ppc/linux.c
		etc/ppc/macosx.c
		etc/sparc/gcc-solaris.c
		etc/sparc/linux.c
		etc/sparc/solaris.c
		etc/x86/freebsd.c
		etc/x86/linux.c
		etc/x86/win32.c
]
------------------------------------------------------------------------
Sat Mar 31 21:47:52 2001
lcc does not output correct type information in symbol table entries:
the type code and data length fields in the .stabs macro are 0.  This
makes debugging quite painful: instead of
	print x
one has to say
	print (double)*(double*)(&x)

For example:
% cat fp.c
#include <stdio.h>
#include <math.h>
#include <stdlib.h>

int
main(int argc, char* argv[])
{
    double x,y;
    x = sqrt(2.0);
    y = x * x;
    printf("x = %25.15g\n", x);
    printf("y = %25.15g\n", y);
    return (EXIT_SUCCESS);
}

% gcc -g3 -S fp.c
% grep '"x:' fp.s
.stabs "x:(0,13)",128,0,8,-24

% lcc -g -S fp.c
% grep '"x' fp.s
.stabs "x:3",128,0,0,-8

The 128 value means a local symbol.  The second 0 is the size.  I
cannot find adequate documentation on the .stabs values, despite
looking in the gcc and gdb sources, and doing extensive searches for
man pages and for <stabs.h> files.
------------------------------------------------------------------------
Mon Apr  2 09:43:27 2001
lcc does not produce debug output in response on -g on mips and alpha
architectures; the assemblers on those systems do not support .stabs
pseudo-ops.  Eventually, support should be added for symbol table
output on those platforms.
------------------------------------------------------------------------
Mon Apr  2 17:54:19 2001

On the sparc/linux platform (only), it is unfortunately necessary to
run "make install" before running "make check", because the former
installs the fixas wrapper script that lcc needs.  If you don't want
to do the full install yet, you can manually install fixas like this:

	mkdir -p $(prefix)/lib/lcc/4.1.beta.8/
	cp ./etc/sparc/fixas.sh $(prefix)/lib/lcc/4.1.beta.8/fixas

This blemish will be removed when we figure out how to eliminate the
fixas.sh wrapper entirely, by changes to etc/sparc.md.
------------------------------------------------------------------------
Fri Apr 13 14:50:14 2001

Another code generator that would be of considerable interest is one
for the Java Virtual Machine: src/java.md.
------------------------------------------------------------------------
Sat Apr 14 14:20:33 2001

Need to run all of the code generators on all of the test .c files,
and then for each platform, extract a list of unique instructions to
compare against those in the .md file.  If any in the latter are
missing, then we need to generate new test C files that will get the
compiler to generate them.
------------------------------------------------------------------------
Sat May  5 09:36:20 2001

Add support for multiple comma-separated GNU/POSIX style options:
-Wx,arg1,arg2,....

[DONE: Mon May  7 11:44:49 2001]
------------------------------------------------------------------------
Mon May  7 18:13:42 2001

The paranoia test on Sun Solaris 2.7 bails out early: during
execution of line 2049

	printf("\tComparison alleges that 1 * Z = %.17e\n",
		Random2);

the program suddenly jumps into exit(), with no usable stack trace.

On Sun Solaris 2.8, execution continues normally, and the program
finally prints

	Program exited normally.

Thus, the test output in sparc/solaris/tst/paranoia.3bk is truncated
after the output line

	Does Multiplication commute?  Testing on 20 random pairs.

Why does this happen?

It is the ONLY test with this failure:

pwd
/usr/tmp/lcc/4.1.beta.9/sparc/solaris/sparc/solaris/tst
foreach f (*)
	cmp /usr/local/src/lcc/lcc-4.1.beta.9/sparc/solaris/tst/${f}bk $f
end
cmp: EOF on /usr/local/src/lcc/lcc-4.1.beta.9/sparc/solaris/tst/paranoia.3bk
------------------------------------------------------------------------
Thu May 10 07:50:20 2001
Need to fix this problem on Alpha GNU/Linux:

	lcc -pg boo.c && ./a.out && gprof a.out > boo.gprof
	gprof: gmon.out file is missing call-graph data

If I translate with lcc, and assemble and link with gcc, the
problem remains:

	lcc -S -pg boo.c
	gcc -pg boo.s && ./a.out && gprof a.out > boo.gprof
	gprof: gmon.out file is missing call-graph data

Thus, -pg must do something more to the .s file:

	gcc -pg -S boo.c
	mv  boo.s goo.s-gcc-pg
	gcc -S boo.c
	diff boo.s goo.s-gcc-pg
	3a4
	>       nop
	12a14,20
	> .data
	>       .align 3
	> $LP0:
	>       .quad 0
	> .text
	>       lda $28,_mcount
	>       jsr $28,($28),_mcount
	...

So, why aren't the _mcount profile instructions generated; they are
for x86/linux, x86/freebsd, and sparc/linux?

FIXED: [10-May-2001] Extra code added to function() in alphalinux.md
to generate the necessary call to _mcount().
------------------------------------------------------------------------
Sat May 12 10:10:06 2001
There are still puzzling problems with the assembler on alpha/linux.
Of the 18 test suite files, tst/src/*.c, there are test failures in
five:

	fields		[get "x = 1 2 3 0 0 0" instead of "x = 1 2 3 0 0 6"]
	stdarg		[stdarg.h support not yet complete]
	struct		[wrong output]
	switch		[output initially correct, but program terminates prematurely]
	yacc		[wrong output]

The incorrect output in fields comes from the third print statement in
main(),

	printf("x = %d %d %d %d %d %d\n", x.a, x.b, x.x, x.y, x.z, x.c);

and only the last item, x.c, is printed incorrectly; it should be 6,
but is 0 instead.

If on Alpha GNU/Linux, I do

	lcc -S fields.c
	sed -e 's/.section .rodata/.rdata/' \
		-e 's/.section .sdata,"aw"/.sdata/' \
		fields.s >foo.s

then on Alpha OSF/1, run

	lcc foo.s && ./a.out

the output is correct.  This strongly suggests that the code
generation on alpha/linux is correct, but the assembly by gas (from
GNU binutils-2.10.1 (the latest version, released 7-Nov-2000)) is
incorrect.

On the Alpha, many of the instructions generated by compilers are
actually macros that the assembly expands.

Stepping a dbx session on OSF/1 shows the expanded instructions, and
the last value pushed onto the stack is indeed the correct value, 6.

A similar session with gdb on GNU/Linux does NOT show the expanded
instruction, and the program counter sometimes steps much more than 4
bytes between instructions.  The last value pushed onto the stack is
0, which is incorrect.

So, is the expanded load instruction doing the wrong thing, or is the
data stored incorrectly?
------------------------------------------------------------------------
Mon May 14 17:00:18 2001

Numerous SGI IRIX 6.x system header files contain #ident directives
which lcc's cpp rejects as fatal errors.  This means that programs
that include non-lcc-provided header files will generally not compile.
There are two possible solutions:

	(1) have configure or etc/mips/irix.c force the use of
	    /lib/cpp instead of lcc's own

	(2) extend lcc's cpp to recognize, but ignore, #ident
            directives

The worse alternative is always having to run lcc as

	lcc -Wo,-cpp=/usr/lib/cpp 

For now, I've chosen option (1), with changes to etc/mips/irix.c.
------------------------------------------------------------------------
