archiel@hercules.UUCP (Archie Lachner) (09/27/84)
There in a bug in the way the 4.2bsd C compiler treats bit fields under some circumstances when optimization is turned on. If there is a bit field 16 bits long that falls on a byte boundary, the optimizer issues a "cvtwl," "movwl," or "movzwl" instruction instead of an "extv" or "extzv" instruction when extracting the field, since the former are more efficient than the latter. However, the address used for the field in any of the former is incorrect. I have short program that documents this bug, if anyone is interested. I don't know if this bug is present on other versions of UNIX, since I only have 4.2 available to me. -- Archie Lachner Logic Design Systems Division Tektronix, Inc. uucp: {ucbvax,decvax,pur-ee,cbosg,ihnss}!tektronix!teklds!archiel CSnet: archiel@tek ARPAnet: archiel.tek@csnet-relay
chris@umcp-cs.UUCP (Chris Torek) (09/29/84)
(Does this REALLY need to go to net.lang.c? Oh well...) Guy Harris posted a fix for this one long ago. It seems that Berkeley never picked up the fix since the bug is still there in the 4.2BSD /lib/c2. Here's RCS diffs. (Thanks, Guy.) [This first one is just to make it use the 4.2 stdio buffering, which means /tmp will (hopefully) have less disk activity] RCS file: RCS/c20.c,v retrieving revision 1.1 diff -b -c1 -r1.1 c20.c *** /tmp/,RCSt1001443 Sat Sep 29 11:49:05 1984 --- c20.c Mon Aug 6 15:57:42 1984 *************** *** 57,59 } ! setbuf(stdin,_sibuf); ++infound; } else if (freopen(*argv, "w", stdout) ==NULL) { --- 57,60 ----- } ! /* setbuf(stdin,_sibuf); */ ! ++infound; } else if (freopen(*argv, "w", stdout) ==NULL) { *************** *** 62,64 } ! setbuf(stdout,_sobuf); argc--; argv++; --- 63,65 ----- } ! /* setbuf(stdout,_sobuf); */ argc--; argv++; [and here's the real fixes] RCS file: RCS/c21.c,v retrieving revision 1.1 diff -b -c1 -r1.1 c21.c *** /tmp/,RCSt1001448 Sat Sep 29 11:49:19 1984 --- c21.c Mon Aug 6 13:43:32 1984 *************** *** 277,279 ** extv $n*8,$8,A,B > cvtbl n+A,B ! ** extv $n*16,$16,A,B > cvtwl n+A,B ** extzv $n*8,$8,A,B > movzbl n+A,B --- 277,279 ----- ** extv $n*8,$8,A,B > cvtbl n+A,B ! ** extv $n*16,$16,A,B > cvtwl 2n+A,B ** extzv $n*8,$8,A,B > movzbl n+A,B *************** *** 279,281 ** extzv $n*8,$8,A,B > movzbl n+A,B ! ** extzv $n*16,$16,A,B > movzwl n+A,B */ --- 279,281 ----- ** extzv $n*8,$8,A,B > movzbl n+A,B ! ** extzv $n*16,$16,A,B > movzwl 2n+A,B */ *************** *** 324,326 else ! sprintf(regs[RT1], "%d%s%s", coff, regs[RT3][0]=='(' ? "":"+", regs[RT3]); --- 324,328 ----- else ! sprintf(regs[RT1], "%d%s%s", ! (flen == 8 ? coff : 2*coff), ! (regs[RT3][0] == '(' ? "" : "+"), regs[RT3]); *************** *** 790,791 register char *cp1,*cp2; int r; char src[C2_ASIZE]; --- 792,794 ----- register char *cp1,*cp2; int r; + int lhssiz, subop; char src[C2_ASIZE]; *************** *** 806,807 } if (p->back->op==CVT || p->back->op==MOVZ) {/* greedy, aren't we? */ --- 809,824 ----- } + /* + * 'pos', 'siz' known; find out the size of the + * left-hand operand of what the bicl will turn into. + */ + if (pos==0) { + if (siz==8) + lhssiz = BYTE;/* movzbl */ + else if (siz==16) + lhssiz = WORD;/* movzwl */ + else + lhssiz = BYTE;/* extzvl */ + } + else + lhssiz = BYTE;/* extzvl */ if (p->back->op==CVT || p->back->op==MOVZ) {/* greedy, aren't we? */ *************** *** 808,810 splitrand(p->back); cp1=regs[RT1]; cp2=regs[RT2]; ! if (equstr(src,cp2) && okio(cp1) && !indexa(cp1) && 0<=(r=isreg(cp2)) && r<NUSE --- 825,840 ----- splitrand(p->back); cp1=regs[RT1]; cp2=regs[RT2]; ! /* ! * If indexa(cp1) || autoid(cp1), the fold may ! * still be OK if the CVT/MOVZ has the same ! * size operand on its left size as what we ! * will turn the bicl into. ! * However, if the CVT is from a float or ! * double, forget it! ! */ ! subop = p->back->subop&0xF;/* type of LHS of ! CVT/MOVZ */ ! if (equstr(src,cp2) && okio(cp1) ! && subop != FFLOAT && subop != DFLOAT ! && subop != GFLOAT && subop != HFLOAT ! && ((!indexa(cp1) && !autoid(cp1)) || lhssiz == subop) && 0<=(r=isreg(cp2)) && r<NUSE *************** *** 810,812 && 0<=(r=isreg(cp2)) && r<NUSE ! && bitsize[p->back->subop&0xF]>=(pos+siz) && bitsize[p->back->subop>>4]>=(pos+siz)) {/* good CVT */ --- 840,842 ----- && 0<=(r=isreg(cp2)) && r<NUSE ! && bitsize[subop]>=(pos+siz) && bitsize[p->back->subop>>4]>=(pos+siz)) {/* good CVT */ *************** *** 818,821 splitrand(p); /* retrieve destination of BICL */ ! if (siz==8 && pos==0) { ! p->combop = T(MOVZ,U(BYTE,LONG)); sprintf(line,"%s,%s",src,lastrand); --- 848,851 ----- splitrand(p); /* retrieve destination of BICL */ ! if ((siz==8 || siz == 16) && pos==0) { ! p->combop = T(MOVZ,U(lhssiz,LONG)); sprintf(line,"%s,%s",src,lastrand); *************** *** 1363,1364 while (*p) if (*p++=='[') return(1); return(0); --- 1393,1402 ----- while (*p) if (*p++=='[') return(1); + return(0); + } + + autoid(p) register char *p; { /* 1-> uses autoincrement/autodecrement; + 0-> doesn't */ + if (*p == '-' && *(p+1) == '(') return(1); + while (*p) p++; + if (*--p == '+' && *--p == ')') return(1); return(0); -- (This page accidently left blank.) In-Real-Life: Chris Torek, Univ of MD Comp Sci (301) 454-7690 UUCP: {seismo,allegra,brl-bmd}!umcp-cs!chris CSNet: chris@umcp-cs ARPA: chris@maryland