donn@sdchema.UUCP (04/08/84)
Here, as promised, are Bob Corbett's changes to f77 to prevent the allocation of subroutine argument temporaries from trashing DO loop limits and other things. I have included the fixes to Bob's changes which I have made, so if you are already running the changes from Berkeley and Bob hasn't sent you the latest round of fixes, you will want to use this code instead. In any case, this supersedes the bug report I sent out titled 'Bug in f77 loop optimizer generates incorrect code (serious!)'. If you have already installed my fix, you will need to remove it. As a reminder, here are the changes needed to remove my fix in exdo() in exec.c. (All source files that I'll be referring to are in /usr/src/f77/src/f77pass1. Also, in each set of diffs, '*' marks old code and '-' marks new or corrected code.) --------------------------------------------------------------------------- *** /tmp/,RCSt1020046 Sat Apr 7 20:23:42 1984 --- exec.c Fri Mar 23 14:50:26 1984 *************** *** 465,471 if( CONSTLIMIT ) ctlstack->domax = DOLIMIT; else ! ctlstack->domax = (expptr) mkaltemp(dotype, PNULL); if( CONSTINCR ) { --- 447,453 ----- if( CONSTLIMIT ) ctlstack->domax = DOLIMIT; else ! ctlstack->domax = (expptr) mktemp(dotype, PNULL); if( CONSTINCR ) { *************** *** 476,482 } else { ! ctlstack->dostep = (expptr) mkaltemp(dotype, PNULL); ctlstack->dostepsign = VARSTEP; } --- 458,464 ----- } else { ! ctlstack->dostep = (expptr) mktemp(dotype, PNULL); ctlstack->dostepsign = VARSTEP; } --------------------------------------------------------------------------- Here are the changes needed for the new set of fixes. Be careful -- they are complicated. Where there are long stretches of new code, it is probably a good idea to clip out the diffs from this article with an editor, remove the diff marks and install them directly into the file. The file 'defs.h' needs a couple new external definitions: --------------------------------------------------------------------------- *** /tmp/,RCSt1020106 Sat Apr 7 20:34:04 1984 --- defs.h Fri Mar 23 14:50:15 1984 *************** *** 117,122 extern flag anylocals; extern chainp templist; extern int maxdim; extern chainp holdtemps; extern struct Entrypoint *entries; --- 133,140 ----- extern flag anylocals; extern chainp templist; + extern chainp argtemplist; + extern chainp activearglist; extern int maxdim; extern chainp holdtemps; extern struct Entrypoint *entries; --------------------------------------------------------------------------- The declarations of these variables are in init.c, and the code needed to reset them is in procinit() in the same file: --------------------------------------------------------------------------- *** /tmp/,RCSt1020131 Sat Apr 7 20:38:06 1984 --- init.c Fri Mar 23 14:50:37 1984 *************** *** 112,117 flag toomanyinit; ftnint curdtelt; chainp templist = NULL; chainp holdtemps = NULL; int dorange = 0; struct Entrypoint *entries = NULL; --- 131,138 ----- flag toomanyinit; ftnint curdtelt; chainp templist = NULL; + chainp argtemplist = CHNULL; + chainp activearglist = CHNULL; chainp holdtemps = NULL; int dorange = 0; struct Entrypoint *entries = NULL; *************** *** 279,284 for(cp = templist ; cp ; cp = cp->nextp) free( (charptr) (cp->datap) ); frchain(&templist); holdtemps = NULL; dorange = 0; nregvar = 0; --- 300,308 ----- for(cp = templist ; cp ; cp = cp->nextp) free( (charptr) (cp->datap) ); frchain(&templist); + for (cp = argtemplist; cp; cp = cp->nextp) + free((char *) (cp->datap)); + frchain(&argtemplist); holdtemps = NULL; dorange = 0; nregvar = 0; --------------------------------------------------------------------------- Subroutine argument temporaries need to be recycled at each statement boundary (not at each call, unfortunately, since the code generator moves the definitions of temporaries to the beginning of each statement; the original Berkeley changes did this incorrectly). This requires a change in the production for 'stat' in gram.head: --------------------------------------------------------------------------- *** /tmp/,RCSt1020164 Sat Apr 7 20:43:40 1984 --- gram.head Fri Mar 23 22:46:53 1984 *************** *** 110,115 err("label already that of a format"); else $1->labtype = LABEXEC; } } | thislabel SINCLUDE filename --- 126,136 ----- err("label already that of a format"); else $1->labtype = LABEXEC; + } + if(!optimflag) + { + argtemplist = hookup(argtemplist, activearglist); + activearglist = CHNULL; } } | thislabel SINCLUDE filename --------------------------------------------------------------------------- A similar change must occur in putopt() in optim.c: --------------------------------------------------------------------------- *** /tmp/,RCSt1020183 Sat Apr 7 20:46:23 1984 --- optim.c Fri Mar 23 22:48:42 1984 *************** *** 179,184 badthing("SKtype", "putopt", sp->type); break; } } --- 195,208 ----- badthing("SKtype", "putopt", sp->type); break; } + + /* + * Recycle argument temporaries here. This must get done on a + * statement-by-statement basis because the code generator + * makes side effects happen at the start of a statement. + */ + argtemplist = hookup(argtemplist, activearglist); + activearglist = CHNULL; } --------------------------------------------------------------------------- Now comes the tough part. A new routine mkargtemp() must be added in proc.c following the code for mkaltmpn(): --------------------------------------------------------------------------- *** /tmp/,RCSt1020214 Sat Apr 7 20:52:40 1984 --- proc.c Fri Mar 23 14:50:58 1984 *************** *** 1003,1008 fprintf(diagfile,"mkaltmpn new offset %d\n", q->memoffset->constblock.const.ci); return(q); } ^L /* VARIOUS ROUTINES FOR PROCESSING DECLARATIONS */ --- 1013,1080 ----- fprintf(diagfile,"mkaltmpn new offset %d\n", q->memoffset->constblock.const.ci); return(q); + } + + + + /* The following routine is a patch which is only needed because the */ + /* code for processing actual arguments for calls does not allocate */ + /* the temps it needs before optimization takes place. A better */ + /* solution is possible, but I do not have the time to implement it */ + /* now. */ + /* */ + /* Robert P. Corbett */ + + Addrp + mkargtemp(type, lengp) + int type; + expptr lengp; + { + ftnint leng; + chainp oldp, p; + Addrp q; + + if (type == TYUNKNOWN || type == TYERROR) + badtype("mkargtemp", type); + + if (type == TYCHAR) + { + if (ISICON(lengp)) + leng = lengp->constblock.const.ci; + else + { + err("adjustable length"); + return ((Addrp) errnode()); + } + } + + oldp = CHNULL; + p = argtemplist; + + while (p) + { + q = (Addrp) (p->datap); + if (q->vtype == type + && (type != TYCHAR || q->vleng->constblock.const.ci == leng)) + { + if (oldp) + oldp->nextp = p->nextp; + else + argtemplist = p->nextp; + + p->nextp = activearglist; + activearglist = p; + + return (q); + } + + oldp = p; + p = p->nextp; + } + + q = autovar(1, type, lengp); + activearglist = mkchain(q, activearglist); + return (q); } ^L /* VARIOUS ROUTINES FOR PROCESSING DECLARATIONS */ --------------------------------------------------------------------------- Finally, the routine putcall() in putpcc.c must be changed to use mkargtemp() instead of mkaltemp(). This is what was causing the breakage before, since putcall() was dipping into the pool of temporaries after the point where that pool is supposed to be restricted. --------------------------------------------------------------------------- *** /tmp/,RCSt1020263 Sat Apr 7 21:03:51 1984 --- putpcc.c Fri Mar 23 22:51:59 1984 *************** *** 1267,1273 int n, first; Addrp t; register expptr q; ! Addrp fval; int type, type2, ctype, qtype, indir; type2 = types2[type = p->vtype]; --- 1300,1306 ----- int n, first; Addrp t; register expptr q; ! Addrp fval, mkargtemp(); int type, type2, ctype, qtype, indir; type2 = types2[type = p->vtype]; *************** *** 1312,1318 { if( ISICON(p->vleng) ) { ! fval = mkaltemp(TYCHAR, p->vleng); n += 2; } else { --- 1345,1351 ----- { if( ISICON(p->vleng) ) { ! fval = mkargtemp(TYCHAR, p->vleng); n += 2; } else { *************** *** 1322,1328 } else if( ISCOMPLEX(type) ) { ! fval = mkaltemp(type, PNULL); n += 1; } else --- 1355,1361 ----- } else if( ISCOMPLEX(type) ) { ! fval = mkargtemp(type, PNULL); n += 1; } else *************** *** 1356,1362 if(indir) putx(q); else { ! t = mkaltemp(qtype = q->headblock.vtype, q->headblock.vleng); putassign( cpexpr(t), q ); putaddr(t, NO); --- 1389,1395 ----- if(indir) putx(q); else { ! t = mkargtemp(qtype = q->headblock.vtype, q->headblock.vleng); putassign( cpexpr(t), q ); putaddr( cpexpr(t), NO ); *************** *** 1359,1365 t = mkaltemp(qtype = q->headblock.vtype, q->headblock.vleng); putassign( cpexpr(t), q ); ! putaddr(t, NO); putcomma(1, qtype, YES); } } --- 1392,1398 ----- t = mkargtemp(qtype = q->headblock.vtype, q->headblock.vleng); putassign( cpexpr(t), q ); ! putaddr( cpexpr(t), NO ); putcomma(1, qtype, YES); } } --------------------------------------------------------------------------- That should keep you busy for a while... Donn Seeley UCSD Chemistry Dept. ucbvax!sdcsvax!sdchema!donn 32 52' 30"N 117 14' 25"W (619) 452-4016 sdcsvax!sdchema!donn@nosc.ARPA