(Improvement on) PCC fix for auto incr+struct/union bug

Chris Torek chris at umcp-cs.UUCP
Thu Nov 22 17:54:17 AEST 1984


Index: lib/pcc/local2.c 4.2BSD Fix

Description:
	The original 4.2BSD PCC mishandles autoincrement operations
	on certain structures and unions.  For example, compiling

		typedef struct { short i, j; } ty;

		f () {
			register ty *sp;

			while (sp++->i);
		}

	produces code that autoincrements r11 ("sp") by 4, rather
	than 2.  elsie!ado posted a fix, but it turned off optimization
	of the same code for types such as

		typedef struct { int i; } ty;

	or

		typedef union { int i; char c; } ty;

	The same bug is probably present in the 4.1 PCC.

Repeat-By:
	(see description)

Fix:
	What's happening is that ``shumul'' is called to attempt to
	share UNARY MULs (i.e., indirection) with predecrements or
	postincrements.  It gets the proper size for everything except
	structures and unions.  (For these, shumul is called only if
	one is accessing the first element of the structure, or an item
	at offset 0 in a union.) The original code assumed that all
	structure elements were four bytes long!  elsie!ado's fix
	actually turned off all shumul struct/union optimizations (I
	forget why, but it's not important).  What I've done is rewrite
	the code to check specifically for STRTY (structures) and
	UNIONTY (unions), and to get the size of the element being
	accessed (by a recursive call).

	This has been installed in our compiler for quite a while now
	and no one has complained, so it is presumably correct.  However,
	I have to apologize for not using the format of the rest of
	the code (I just couldn't read what I wrote that way).

	Finally, the fix itself:  replace local2$shumul() with the
	following:

-------------------------------------------------------------------
/* reshape a UNARY MUL, if possible */
shumul (p) register NODE *p; {
	register int o;
	extern int xdebug;

	if (xdebug) {
		printf("\nshumul:op=%d,lop=%d,rop=%d", p->in.op,
			p->in.left->in.op, p->in.right->in.op);
		printf(" prname=%s,plty=%d, prlval=%D\n", p->in.right->in.name,
			p->in.left->in.type, p->in.right->tn.lval);
	}

	o = p->in.op;
	if (o == NAME || (o == OREG && !R2TEST(p->tn.rval)) || o == ICON)
		return(STARNM);

	/* can we make an auto-incr or auto-decr out of it? */
	if ((o == INCR || o == ASG MINUS) &&
	    (p->in.left->in.op == REG && p->in.right->in.op == ICON) &&
	    p->in.right->in.name[0] == '\0') {
		o = szumul(p->in.left->in.type, p->in.type);
		if (edebug)
			printf("szumul=>%d\n", o);
		return(p->in.right->tn.lval == o ? STARREG : 0);
	}
	return(0);
}

/* Return the size of the object which would be dereferenced by a
   UNARY MUL operator (0 iff unknown) */
szumul(ty, sty)
TWORD ty;			/* type of object */
TWORD sty;			/* type of structure ref (if any) */
{
	register TWORD dty;

	if (!ISPTR(ty))
		cerror("szumul: ty not a pointer");
	dty = DECREF(ty);
	switch (dty) {
	case CHAR:
	case UCHAR:
		return(1);

	case SHORT:
	case USHORT:
		return(2);

	case INT:
	case UNSIGNED:
	case LONG:
	case ULONG:
	case FLOAT:
		return(4);

	case DOUBLE:
		return(8);

	case STRTY:
	case UNIONTY:
		if (!ISPTR(sty))
			return(0);
		return(szumul(sty, UNDEF));

	default:
		if (ISPTR(dty))
			return(4);
	}
	if (edebug)
		printf("szumul can't figure out type %d\n", dty);
	return(0);
}
-------------------------------------------------------------------
(And no, I can't use ``szty'' or whatever it was.)

Onward! to more optimal optimization,
-- 
(This line accidently left nonblank.)

In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (301) 454-7690
UUCP:	{seismo,allegra,brl-bmd}!umcp-cs!chris
CSNet:	chris at umcp-cs		ARPA:	chris at maryland



More information about the Comp.bugs.4bsd.ucb-fixes mailing list