BSD 4_3_Tahoe development
authorCSRG <csrg@ucbvax.Berkeley.EDU>
Fri, 20 May 1988 13:27:45 +0000 (05:27 -0800)
committerCSRG <csrg@ucbvax.Berkeley.EDU>
Fri, 20 May 1988 13:27:45 +0000 (05:27 -0800)
Work on file usr/src/lib/pcc/pcc.vax/LOG

Synthesized-from: CSRG/cd2/4.3tahoe

usr/src/lib/pcc/pcc.vax/LOG [new file with mode: 0644]

diff --git a/usr/src/lib/pcc/pcc.vax/LOG b/usr/src/lib/pcc/pcc.vax/LOG
new file mode 100644 (file)
index 0000000..d9709bf
--- /dev/null
@@ -0,0 +1,489 @@
+There was a bug which caused compiler errors when floating values were
+assigned to bit fields.  Some overenthusiastic optimization on my part
+led to a float-to-int conversion on the rhs of the assignment being
+dropped.  Bit fields are now treated as a special case.  [pcc.vax:
+local2.c]
+
+At the instigation of Rob Pike, enums were neutered: they now behave
+exactly like ints.  The only traces of Johnson's treatment of enums are
+warnings about clashes between one enum type and another enum type in
+certain expressions.  This fix was trickier than it looked; it would
+have been much simpler to drop ALL warnings about enums, as Rob would
+recommend.  [mip: trees.c]
+
+Arthur Olsen pointed out a bug with the evaluation of constant
+expressions -- the usual arithmetic conversions are not always
+performed.  Rather than follow Arthur's simple suggestion, I decided to
+be safe and arranged to use the same conversion code on constants that
+we use on variables.  We short-cut the test if the operand(s) are ints,
+which is the usual case, so the impact on compile time should be
+small.  [mip: trees.c]
+
+Guy Harris noted that chkpun() considered multiply dimensioned arrays
+and multiply indirect pointers to be the same thing, which they are
+most certainly not.  His fix causes an 'illegal pointer combination'
+warning to be emitted for code like:
+
+       char **cpp, c2a[10][20]; cpp = c2a; cpp[5][3] = 'a';
+
+The new code is actually simpler than the old...  [mip: trees.c]
+
+Another irritation of Rob Pike's is fixed -- the old-style assignment
+ops have been ifdef'ed out.  No more of those obnoxious 'ambiguous
+assignment: assignment op taken' messages!  [mip: scan.c]
+
+Yet another Rob Pike complaint: you couldn't refer directly to the
+members of a structure which had been returned by a function.  You may
+now utter things like 'f().a' and get away with them.  The illegal form
+'(&f())->a' used to work; since this has the same tree representation
+as the legal form, an ugly wart was added to the action for '&' which
+specifically rules this form out.  To be consistent, a similar
+exception was made for expressions of the form '(a = b).c'.  [mip:
+cgram.y]
+
+Moved configuration flags from Makefile into macdefs.h and converted
+some more trivial routines into macros.  This cleans up the Makefile
+considerably and consolidates assembler-dependent flags.  [pcc.vax:
+macdefs.h, code.c, order.c, Makefile; mip: onepass.h]
+
+More efficiency hacks: the compiler now does its best to avoid emitting
+ANY code after an error is detected.  Previously only code generation
+through the code table was suppressed after an error.  This change can
+buy up to 25% in speed improvements if the dbx stab flag is enabled.
+The latest 'ccom' runs twice as fast as the 4.2 BSD compiler in this
+situation...  [pcc.vax:  macdefs.h, local.c, code.c; mip: cgram.y,
+scan.c, pftn.c]
+
+For ANSI compatibility, we now accept void expressions in the colon
+part of a conditional expression.  Both subexpressions under the colon
+operator must be void if one is void.  The overall type of the
+conditional expression is void in this case.  [mip: trees.c]
+
+As long as we're doing away with old-fashioned assignment operators, we
+might as well terminate old-fashioned initializations too.  [mip: cgram.y]
+
+A fix from James Schoner for bitfield assignments was installed.  The
+problem was that the rhs of a bitfield assignment was used as its
+value, an overlooked aspect of the several earlier bug fixes for
+problems of this variety.  The bug caused
+
+       struct { unsigned a:4, b:3, c:2; } x;
+       int i;
+       i = x.b = 255;
+
+to store 255 in i instead of 7.  [pcc.vax: table.c, local2.c]
+
+Scanner code was added to handle the System V/ANSI preprocessor
+extensions #ident and #pragma.  Currently #ident is ignored.  #pragma
+may be used as a substitute for lint-style comment directives; e.g. use
+'#pragma LINTLIBRARY' for '/* LINTLIBRARY */'.  The #pragma stuff
+requires the hacked-up cpp with ANSI extensions which may eventually be
+put into circulation here at Utah.  The #line control from cpp is now
+recognized with the same syntax by ccom.  Unknown control lines elicit
+a warning.  A small bug is fixed by this new code -- previously #ident
+and other unknown controls caused the line control mechanism to get
+screwed up, so that bogus dbx stabs were put in the output.  [mip:
+scan.c]
+
+There seems to be a loophole in initializations -- apparently it is
+legal to initialize a bitfield with a symbolic constant (i.e. the
+address of something).  No loader that I know of will handle this!  The
+compiler now emits an error when someone tries this trick; it really
+can't do any better.  [mip: pftn.c]
+
+Someone complained that all illegal characters were being printed as
+octal numbers in the error message.  This was changed so that printable
+characters are printed normally, and all funny characters are printed
+in C 'char' style.  [mip: scan.c]
+
+Conversion of unsigned constants to floating point values was broken
+because the requisite cast in makety() had been commented out!  Argh.
+Unsigned comparisons of constants were similarly botched.  [mip: trees.c]
+
+Ray Butterworth made a sensible suggestion that array definitions which
+aren't external and allocate no storage should elicit errors.  I
+modified his suggestion slightly by moving the test into nidcl(), where
+we can be sure that an array isn't being initialized.  I also adopted
+his suggestion for a lint warning for arrays with explicit dimensions
+that are lost by the rule that converts array types into pointer types
+in formal arguments; the warning is contingent on lint's -h flag.
+[mip: pftn.c]
+
+The structures for fpn and dpn nodes (floating point constants) were
+changed to make them conform in shape to the other nodes.  [mip: ndu.h]
+
+Overenthusiastic SCONV optimization code in optim2() led to functions
+not cooperating with certain casts; e.g.
+
+       unsigned char x(); ... y((char)x()) ...
+
+failed to sign-extend the result of x().  [pcc.vax: local2.c]
+
+A bug in outstruct() caused it to check 'stab[-1].name == NULL' for
+unnamed structures.  For some reason this didn't break until my recent
+lint fixes tweaked the compiler in some subtle way...  [pcc.vax: stab.c]
+
+The makefile was changed to pass C options to lint properly and to drop
+the '-a' flag to lint in the 'lintall' entry.  '-a' really ought to
+work but unfortunately the arrangement of 'int'-like types in the
+compiler is extremely confusing and inconsistent, so I eventually gave
+up trying to force the issue.  Sam Leffler's 'rel.c' for release
+information was also added.  [pcc.vax: Makefile, rel.c]
+
+I fixed defid() so that it now insists that all argument type
+declarations must refer to names in the argument list.  Previously you
+could get away with:
+
+       int a;
+       x()
+               int a;
+       { ... }
+
+Use of 'a' in the body of x() would elicit the immortal error message
+'warning: bad arg temp'.  [mip: pftn.c]
+
+For some reason, mainp2() in the two-pass version of the compiler had a
+switch statement with two 'default' cases.  I zapped the obvious one.
+[mip: reader.c]
+
+Botched initializations sometimes left the declarations code in a funny
+state, so a fixinit() routine was invented to aid error recovery.  For
+example, the following illegal program forced a core dump:
+
+       char m[] = ;
+       x() {
+               y("splat");
+       }
+
+The compiler tried to read "splat" into m[] and died horribly.  [mip:
+cgram.y, pftn.c]
+
+The compiler now warns 'can't take size of function' when asked to do
+something amazing like '... void f(); ... if (f[10]) ...'.  Previously
+it produced a compiler error instead.  [mip: pftn.c]
+
+If a program tried to access a value below the argument list on the
+stack using the clever tactic of manipulating the address of an
+argument, it drew a warning 'bad arg temp'.  For the sake of these
+clever programs, the warning has been suppressed.  [pcc.vax: local2.c]
+
+The assembler would sometimes print 'Branch too long: try -J flag' even
+when you used the -J flag and when there was no reason for it to be
+making long branches.  This was due to a bug in jxxxfix() which caused
+tests for explodable branch instructions to terminate early in later
+phases of the topological sort, because the loop termination code
+didn't take into account the fact that not all code addresses are
+updated by jxxxbump().  The fix is to match the pointer to the data
+structure for the code in the sorted table rather than check for its
+generated address.  [as: asjxxx.c]
+
+The peephole optimizer normally compares instructions for equality
+based on their instruction type and their operands.  Unfortunately
+several instructions are too complex for c2 to handle and are given an
+instruction type of 0; thus all such instructions compared equal.  The
+equop() routine was changed to test the names of these '0' type
+instructions for equality.  [c2: c21.c]
+
+The compiler sometimes botched computations into stack temporaries by
+treating expressions like '-40(fp)[r1]' as permissible temporaries.  I
+rewrote the shtemp() routine to make it explicit that the 'stack
+temporary' goal in code generation means precisely that the final
+expression must not contain any references to temporary registers (like
+r1).  I had to add a couple templates to the code table to push
+exceedingly complex OREG expressions onto the stack when this goal is
+attempted.  [pcc.vax: local2.c, table.c]
+
+A bug sometimes caused a redeclaration of an array in an inner scope to
+affect the outer array when the outer array was incompletely specified
+(by leaving out the most significant dimension).  For example:
+
+       extern int a[];
+       x(){ int a[10]; }
+       int a[20];
+
+This code would elicit the error 'foo.c, line 3: redeclaration of a'.
+The routine defid() is used to enter new definitions; for some reason
+scope problems are not resolved in defid() until much other code has
+been executed, including code that deals with filling out array sizes.
+The change makes defid() notice inner scopes with auto and register
+declarations earlier than usual.  [mip: pftn.c]
+
+Case expressions are explicitly restricted to contain only int constants,
+char constants and sizeof expressions (C Reference Manual section 15).
+Previously the compiler didn't test for expressions like '(int) &foo[10]'
+and thus it would generate some rather bogus code.  Expressions which
+resolve to names now elicit the same 'non-constant case expression'
+warning which you receive for variables.  [mip: cgram.y]
+
+The value of an assignment to an unsigned bitfield was signed through
+an oversight in the code table.  [pcc.vax: table.c]
+
+From Sam Kendall, a fix to prevent structs, unions, floats, doubles
+and void from being cast to pointer types.  [mip: trees.c]
+
+Some relict code in moditype() was causing void functions not to be
+converted into pointers in some situations.  [mip: trees.c]
+
+A minor optimization -- when the lhs of a simple assignment op (&=, |=,
+^=, +-, -=) is smaller than int size, we can sometimes pun the rhs and
+avoid promoting the lhs to int, performing the operation in int width
+and converting from int back to the lhs type.  For example:
+
+       register char *ap, *bp;
+       *ap++ |= *bp << 1;
+
+This used to require 7 instructions, but now needs only 3.  [pcc.vax:
+table.c]
+
+At some point I added code to conval() to balance types before
+performing constant folding...  While hacking on the tahoe compiler, I
+decided that this code was too complex and replaced it with equivalent
+code that's shorter and easier to understand.  [mip: trees.c]
+
+Lines containing multiple statements were broken up for the sake of
+tracing with the source debugger in tcheck() and talloc().  [mip:
+common.c]
+
+I discovered that the C compiler called urem() in three different
+places with a constant divisor...  In my subsequent rampage I hacked
+the compiler to generate inline code for all unsigned division and
+modulus operations with constant divisors.  The largest inline
+expansion should use only 5 instructions, with most using just 3 or 4.
+The changes touched several files but really weren't very messy.
+[mip:  pass1.h, match.c; pcc.vax: local2.c, order.c, table.c]
+
+A lot of new code was added to handle a really simple problem:
+
+       unsigned char uc = 255;
+       if (uc == -1) ...
+
+This incorrectly tested true, because the compiler generated a test
+that looked only at the low order byte of the constant.  Not only that,
+but the compiler didn't realize that this test could be short-
+circuited, since -1 is equal to 4294967295 unsigned and is hence out of
+the range of an unsigned char.  Rather than add lots of cruft to the
+code table, I shoved it into optim2() -- the compiler now picks up all
+the absurd cases where a constant is out of the range of precision of
+a variable it's tested against.  To avoid having to write lots of code
+templates to handle unbalanced unsigned/signed expressions, I forced
+tymatch() to take notice of unbalanced expressions and promote the
+signed operand to unsigned (except with assignment operators, sigh).
+This change in turned required tweaks in autoincr() and in the code
+table to get code quality back.  I hope I can come up with a better way
+to do this...  [mip: trees.c; pcc.vax: local2.c, order.c, table.c]
+
+The value of TNULL was changed from 'pointer to undef' to 'pointer to
+member of enum' so that 'void *' can be a real type.  TNULL is used to
+tag unused symbol table slots.  [mip: manifest.h]
+
+A bug in clearst() led to problems with 'schain botch' errors.  When a
+hash collision occurs, a symbol is (linearly) rehashed; if the symbol
+which forced the rehash is deleted, the relook() loop in clearst() will
+cause another symbol with the same hash code to move up and replace the
+deleted symbol.  Torek's 'schain' hack for speedy identification of
+symbols at the same block level will get screwed up by this operation
+since it relies on a linked list of table entries -- moving an entry
+garbles the list.  How did this code ever work before?  [mip: pftn.c]
+
+Changed putins() in ascode.c in the assembler to permit 0(pc) as a
+write operand...  Previously the assembler automatically optimized
+this to (pc), which is an illegal operand.  [as.vax: ascode.c]
+
+The complement of an unsigned char or unsigned short value should have
+its high bits set, since the 'usual arithmetic conversions' widen these
+small integers 'before' the operation.  [pcc.vax: table.c]
+
+A minor code improvement in ccom led to problems in c2 -- c2 was able
+to optimize sequences like 'cvtbl -4(fp),r0; bicl2 $-256,r0' but not
+the (shorter and faster) 'cvtbl -4(fp),r0; movzbl r0,r0'.  A change in
+bflow() causes redundant conversions to be noted and removed, restoring
+code quality.  [c2: c21.c]
+
+A typo in the 'bitsize' array definition resulted in an unterminated
+comment which screwed up the bit sizes for several types.  I only
+noticed this because I ran the source off with vgrind and the error
+was exposed by comment highlighting...  [c2: c21.c]
+
+An earlier change to conval() caused LONG and ULONG types to be hacked
+into INT and UNSIGNED; this was fine for the (VAX) compiler, but led
+to inconsistencies with lint.  [mip: trees.c]
+
+When a syntax error occurs, the parser throws away tokens until it can
+enter a known state.  If a string or character constant delimiter is
+tossed, the parser will try to interpret the contents of the constant
+as code and can get very confused.  A hack was added to yylex() to
+detect this situation -- basically, if a delimiter is seen but the
+string or character constant has not been processed by lxstr() at the
+next call to yylex(), yylex() will call lxstr() itself and dispose of
+the rest of the constant.  [mip: scan.c]
+
+Following a suggestion by Arthur Olsen, the production for 'switch' was
+modified to complain about constant switch expressions with 'lint -h'.
+[mip: cgram.y]
+
+Another Arthur Olsen bug report pointed out a problem with increment
+operations that don't match a code template...  Two attempts at
+rewriting the increment are made: the first tries to turn the lvalue
+operand into an OREG, and the second applies a tree transformation to
+convert 'x++' into '(x += sizeof x) - sizeof x'.  A mistake in the
+routine setincr() caused the lvalue operand in its entirety to be
+generated into a register instead of just the lvalue operand's address,
+producing something like 'r0 = x, (r0 += sizeof x) - sizeof x' instead
+of 'r0 = &x, (*r0 += sizeof x) - sizeof x'.  [pcc.vax: order.c]
+
+Better code for floating post-increment and -decrement can be generated
+with a simple change to the code table and to zzzcode() so that the
+same hack for ordinary post-increment will work for floating point too.
+[pcc.vax: local2.c, table.c]
+
+I added Arthur Olsen's massive lint fixes for typechecking printf().
+It sure would be nice if there were a way to specify new printf-like
+commands at execute time, perhaps through lint directives embedded in
+include files.  [lint: lint.c]
+
+Arthur's warning about superfluous backslashes was added to lxstr().
+Rather than adding Arthur's (expensive) code for warning about the
+use of '$', I simply made it illegal (unless 'VMS' is defined).  I
+also took the opportunity to remove '`' gcos BCD constants.  I made
+a slight alteration to yylex() to cause it to eat unknown characters
+rather than punt, since this seemed more useful.  [mip: scan.c]
+
+Lint would sometimes print a bogus 'i set but not used' warning in
+situations like this:
+
+       static int i;
+       static int *ip = &i;
+
+       i = 1;
+       return *ip;
+
+If you moved the initialization out of the declaration, the warning
+disappeared.  I installed Arthur's hack for forcing lint to examine
+initializations.  This causes lint to treat initializations of auto,
+register and static variables as 'uses' and to ignore sizeof
+expressions as 'uses'.  Also, '&i' in a static or external
+initialization is now a 'set' and a 'use' of 'i'.  [lint: lint.c; mip:
+cgram.y, pftn.c]
+
+VARARGS0 is now correctly treated differently from plain VARARGS.
+I don't remember who originally noticed this...  [lint: lint.c,
+lpass2.c]
+
+The register allocation code failed to 'share' register pairs.  I don't
+know why this escaped notice for this long...  I added a bit in the
+'busy' array to keep track of pairs and modified the code in usable()
+to notice pairs and try to 'share' them.  Some other code which treated
+the values of busy[] elements as arithmetic values had to be changed;
+there is now a macro which performs the proper test.  [mip: allo.c,
+match.c, pass2.h]
+
+Some extensive code tweaking...  (1) If order() is called on to rewrite
+a UNARY MUL node and that node has a usable index expression, we now
+try to rewrite the base into a register so that oreg2() will produce a
+doubly-indexed OREG.  This is usually an impressive space saving.  (2)
+Instead of laboriously copying a constant 0.0 in data space to clear a
+double or a float, we issue the proper 'clrd' or 'clrf'.  This is done
+by a trick using an alternate prtdcon() routine; I'm not sure who
+invented it.  I guess I'm still not prepared to hack in support for
+floating literals and immediate constants.  (3) The conversion code now
+handles stack pushes directly, which often saves a spill to register.
+With very little adjustment, this also buys us optimally small pushes
+of constants.  (4) Pointer comparisons are now unsigned; I'm not sure
+what this really buys us, but I added it anyway.  (5) AND tests against
+constants are 'small' if both the constant and the other operand are
+also 'small'.  (6) base() now recognizes that NAME nodes can be used in
+pc relative deferred indexed addressing, which is much more compact
+than the equivalent code to compute the address into a register and
+indirect through it.  (7) The optimization code for ANDing with a
+constant now tries to produce a positive mask when small types are used
+so that literal operands are possible; a side effect is that the code
+is more readable.  (8) UCHAR/USHORT to FLOAT/DOUBLE conversions take an
+extra step through INT type to avoid the overhead of an UNSIGNED to
+FLOAT/DOUBLE conversion.  (9) If a logical operator sits above a pair
+of FLOAT to DOUBLE conversions, the conversions are deleted.  (10) Vast
+numbers of redundant or useless templates were deleted from the code
+table.  (11) Conversions to FLOAT in double-only arithmetic now go to
+the trouble of clipping off excess precision from INT and DOUBLE
+operands.  (12) DOUBLE to DOUBLE conversions introduced by reclaim()
+are now silently deleted in the table.  (13) A few 'movd's were turned
+into 'movq's -- more work needs to be done to make this consistent.
+[mip: reader.c; pcc.vax: macdefs.h, local.c, local2.c, table.c]
+
+A bug which caused assignment op expressions with an unsigned char or
+unsigned short lhs and a floating rhs to treat the lhs as signed was
+fixed.  Some conversion-related stuff which used to be done in the
+table is now done in sconv() so that it's easier to handle and so that
+zzzcode() and its descendants can more safely perform conversions by
+calling zzzcode(p, 'A').  [pcc.vax: local2.c, table.c]
+
+The code for setting the type of a floating point constant was bogus.
+A floating constant was float if it fit in a float without loss of
+precision, otherwise it was double.  This caused silliness like
+unexpectedly losing low order bits of integers in mixed floating and
+integral expressions.  The fix was to adopt the ANSI proposal that all
+floating constants are type double unless they bear an 'f' or 'F'
+suffix, in which case they are type float.  (Note that a cast to float
+has the same effect as a 'f' suffix and is just as efficient, but I
+conceded to the evident popularity of the 'f' suffix...)  [mip: scan.c;
+pcc.vax: local.c]
+
+The ASG OPSIMP templates that produce byte and word instructions for
+byte and word destinations weren't being activated very often because
+the constant operands weren't normalized.  I added code to optim2() to
+appropriately reduce the range of constant operands of ASG OPSIMP
+operators and sign-extend.  This blows away many useless conversions to
+and from int.  [pcc.vax: local2.c]
+
+The template for assignment ops with unsigned char/short lhs and
+floating rhs indicated register sharing for the wrong operand...
+[pcc.vax: table.c]
+
+The new template that handled OREG for INTEMP failed to take into
+account the size variation in OREG objects.  [pcc.vax: table.c]
+
+The offstar() routine tries to tweak UNARY MUL trees so that they can
+be handled most effectively by VAX addressing modes.  The code for
+identifying index expressions was adjusted so that more indexed
+addressing modes can be produced.  [pcc.vax: order.c]
+
+Bogus error messages were being emitted for certain initializations
+following an earlier legitimate error.  It turns out that the
+optimization to prevent initialization code from being emitted after
+errors was preventing the initializer offset counter from being
+updated, and when this occurs, the initialization code screws up -- for
+example, string constants appear to be zero length.  The initialization
+code now always updates the offset even if errors have been detected,
+although code generation is still suppressed.  [pcc.vax: local.c]
+
+An assignment to a bitfield in an indexed int-width structure led to
+code generation failure due to an indexed OREG child of FLD.  This is
+taboo because the VAX field instructions have byte-size side effects,
+and code in clocal() arranged for indexed structs to have int width.
+I changed clocal() to use byte width instead and it appears to work now
+(and even uses indexed byte addressing correctly).  [pcc.vax: local.c]
+
+For some reason the unsigned-to-floating conversion code has always
+been long and complex when it could be short and simple.  I used the
+simple code in the Tahoe compiler but didn't think to put it in the VAX
+compiler until prodded by Robert Firth...  [pcc.vax: local2.c]
+
+John Gilmore noticed that the ! operator didn't work with floating
+constants; this was pretty easy to fix.  [mip: trees.c]
+
+For some reason, opact() put left and right shifts through tymatch().
+The type balancing of tymatch() is wrong for shifts -- the type of the
+shift depends only on the left operand, while the right operand is
+converted to int.  We now use the shift special case in buildtree() to
+fix the type.  [mip: trees.c]
+
+Following ANSI (for once) we eliminate warnings for pointer conversions
+involving void *.  [mip: trees.c]
+
+There were at least a couple bugs in c2 with code that converts 'ashl
+$2,rA,rB; movab _x[rB],rC' into 'moval _x[rB],rC'; one caused the type
+to be wrong ('movab' for 'moval'), one caused neighboring instructions
+to get deleted.  [c2.vax: c21.c]
+
+A branch to a redundant test sometimes resulted in c2's deleting the
+label too, even if the label itself was not redundant.  [c2.vax: c21.c]
+