13191Smckusick /* Copyright (c) 1979 Regents of the University of California */ 23191Smckusick 3*7589Speter static char sccsid[] = "@(#)fhdr.c 1.4 07/29/82"; 43191Smckusick 53191Smckusick #include "whoami.h" 63191Smckusick #include "0.h" 73191Smckusick #include "tree.h" 83191Smckusick #include "opcode.h" 93191Smckusick #include "objfmt.h" 103191Smckusick #include "align.h" 113191Smckusick 123191Smckusick /* 133191Smckusick * this array keeps the pxp counters associated with 143191Smckusick * functions and procedures, so that they can be output 153191Smckusick * when their bodies are encountered 163191Smckusick */ 173191Smckusick int bodycnts[ DSPLYSZ ]; 183191Smckusick 193191Smckusick #ifdef PC 203191Smckusick # include "pc.h" 213191Smckusick # include "pcops.h" 223191Smckusick #endif PC 233191Smckusick 243191Smckusick #ifdef OBJ 253191Smckusick int cntpatch; 263191Smckusick int nfppatch; 273191Smckusick #endif OBJ 283191Smckusick 293191Smckusick /* 303191Smckusick * Funchdr inserts 313191Smckusick * declaration of a the 323191Smckusick * prog/proc/func into the 333191Smckusick * namelist. It also handles 343191Smckusick * the arguments and puts out 353191Smckusick * a transfer which defines 363191Smckusick * the entry point of a procedure. 373191Smckusick */ 383191Smckusick 393191Smckusick struct nl * 403191Smckusick funchdr(r) 413191Smckusick int *r; 423191Smckusick { 433191Smckusick register struct nl *p; 443191Smckusick register *il, **rl; 453302Smckusic struct nl *cp, *dp; 463302Smckusic int s, o, *pp; 473191Smckusick 483191Smckusick if (inpflist(r[2])) { 493191Smckusick opush('l'); 503191Smckusick yyretrieve(); /* kludge */ 513191Smckusick } 523191Smckusick pfcnt++; 533191Smckusick parts[ cbn ] |= RPRT; 543191Smckusick line = r[1]; 553191Smckusick if (r[3] == NIL && (p=lookup1(r[2])) != NIL && bn == cbn) { 563191Smckusick /* 573191Smckusick * Symbol already defined 583191Smckusick * in this block. it is either 593191Smckusick * a redeclared symbol (error) 603191Smckusick * a forward declaration, 613191Smckusick * or an external declaration. 62*7589Speter * check that forwards are of the right kind: 63*7589Speter * if this fails, we are trying to redefine it 64*7589Speter * and enter() will complain. 653191Smckusick */ 66*7589Speter if ( ( ( p->nl_flags & NFORWD ) != 0 ) 67*7589Speter && ( ( p->class == FUNC && r[0] == T_FDEC ) 68*7589Speter || ( p->class == PROC && r[0] == T_PDEC ) ) ) { 693191Smckusick /* 703191Smckusick * Grammar doesnt forbid 713191Smckusick * types on a resolution 723191Smckusick * of a forward function 733191Smckusick * declaration. 743191Smckusick */ 753191Smckusick if (p->class == FUNC && r[4]) 763191Smckusick error("Function type should be given only in forward declaration"); 773191Smckusick /* 783191Smckusick * get another counter for the actual 793191Smckusick */ 803191Smckusick if ( monflg ) { 813191Smckusick bodycnts[ cbn ] = getcnt(); 823191Smckusick } 833191Smckusick # ifdef PC 843191Smckusick enclosing[ cbn ] = p -> symbol; 853191Smckusick # endif PC 863191Smckusick # ifdef PTREE 873191Smckusick /* 883191Smckusick * mark this proc/func as forward 893191Smckusick * in the pTree. 903191Smckusick */ 913191Smckusick pDEF( p -> inTree ).PorFForward = TRUE; 923191Smckusick # endif PTREE 933191Smckusick return (p); 943191Smckusick } 953191Smckusick } 963191Smckusick 973191Smckusick /* if a routine segment is being compiled, 983191Smckusick * do level one processing. 993191Smckusick */ 1003191Smckusick 1013191Smckusick if ((r[0] != T_PROG) && (!progseen)) 1023191Smckusick level1(); 1033191Smckusick 1043191Smckusick 1053191Smckusick /* 1063191Smckusick * Declare the prog/proc/func 1073191Smckusick */ 1083191Smckusick switch (r[0]) { 1093191Smckusick case T_PROG: 1103191Smckusick progseen = TRUE; 1113191Smckusick if (opt('z')) 1123191Smckusick monflg = TRUE; 1133191Smckusick program = p = defnl(r[2], PROG, 0, 0); 1143191Smckusick p->value[3] = r[1]; 1153191Smckusick break; 1163191Smckusick case T_PDEC: 1173191Smckusick if (r[4] != NIL) 1183191Smckusick error("Procedures do not have types, only functions do"); 1193191Smckusick p = enter(defnl(r[2], PROC, 0, 0)); 1203191Smckusick p->nl_flags |= NMOD; 1213191Smckusick # ifdef PC 1223191Smckusick enclosing[ cbn ] = r[2]; 1233838Speter p -> extra_flags |= NGLOBAL; 1243191Smckusick # endif PC 1253191Smckusick break; 1263191Smckusick case T_FDEC: 1273191Smckusick il = r[4]; 1283191Smckusick if (il == NIL) 1293191Smckusick error("Function type must be specified"); 1303191Smckusick else if (il[0] != T_TYID) { 1313191Smckusick il = NIL; 1323191Smckusick error("Function type can be specified only by using a type identifier"); 1333191Smckusick } else 1343191Smckusick il = gtype(il); 1353191Smckusick p = enter(defnl(r[2], FUNC, il, NIL)); 1363191Smckusick p->nl_flags |= NMOD; 1373191Smckusick /* 1383191Smckusick * An arbitrary restriction 1393191Smckusick */ 1403191Smckusick switch (o = classify(p->type)) { 1413191Smckusick case TFILE: 1423191Smckusick case TARY: 1433191Smckusick case TREC: 1443191Smckusick case TSET: 1453191Smckusick case TSTR: 1463191Smckusick warning(); 1473191Smckusick if (opt('s')) { 1483191Smckusick standard(); 1493191Smckusick } 1503191Smckusick error("Functions should not return %ss", clnames[o]); 1513191Smckusick } 1523191Smckusick # ifdef PC 1533191Smckusick enclosing[ cbn ] = r[2]; 1543838Speter p -> extra_flags |= NGLOBAL; 1553191Smckusick # endif PC 1563191Smckusick break; 1573191Smckusick default: 1583191Smckusick panic("funchdr"); 1593191Smckusick } 1603191Smckusick if (r[0] != T_PROG) { 1613191Smckusick /* 1623191Smckusick * Mark this proc/func as 1633191Smckusick * being forward declared 1643191Smckusick */ 1653191Smckusick p->nl_flags |= NFORWD; 1663191Smckusick /* 1673191Smckusick * Enter the parameters 1683191Smckusick * in the next block for 1693191Smckusick * the time being 1703191Smckusick */ 1713191Smckusick if (++cbn >= DSPLYSZ) { 1723191Smckusick error("Procedure/function nesting too deep"); 1733191Smckusick pexit(ERRS); 1743191Smckusick } 1753191Smckusick /* 1763191Smckusick * For functions, the function variable 1773191Smckusick */ 1783191Smckusick if (p->class == FUNC) { 1793191Smckusick # ifdef OBJ 1803191Smckusick cp = defnl(r[2], FVAR, p->type, 0); 1813191Smckusick # endif OBJ 1823191Smckusick # ifdef PC 1833191Smckusick /* 1843191Smckusick * fvars used to be allocated and deallocated 1853191Smckusick * by the caller right before the arguments. 1863191Smckusick * the offset of the fvar was kept in 1873191Smckusick * value[NL_OFFS] of function (very wierd, 1883191Smckusick * but see asgnop). 1893191Smckusick * now, they are locals to the function 1903191Smckusick * with the offset kept in the fvar. 1913191Smckusick */ 1923191Smckusick 1933191Smckusick cp = defnl(r[2], FVAR, p->type, 1943302Smckusic (int)-leven(roundup( 1953302Smckusic (int)(DPOFF1+lwidth(p->type)), 1963302Smckusic (long)align(p->type)))); 1973838Speter cp -> extra_flags |= NLOCAL; 1983191Smckusick # endif PC 1993191Smckusick cp->chain = p; 2003191Smckusick p->ptr[NL_FVAR] = cp; 2013191Smckusick } 2023191Smckusick /* 2033191Smckusick * Enter the parameters 2043191Smckusick * and compute total size 2053191Smckusick */ 2063302Smckusic p->value[NL_OFFS] = params(p, r[3]); 2073302Smckusic /* 2083302Smckusic * because NL_LINENO field in the function 2093302Smckusic * namelist entry has been used (as have all 2103302Smckusic * the other fields), the line number is 2113302Smckusic * stored in the NL_LINENO field of its fvar. 2123302Smckusic */ 2133302Smckusic if (p->class == FUNC) 2143302Smckusic p->ptr[NL_FVAR]->value[NL_LINENO] = r[1]; 2153302Smckusic else 2163302Smckusic p->value[NL_LINENO] = r[1]; 2173191Smckusick cbn--; 2183191Smckusick } else { 2193191Smckusick /* 2203191Smckusick * The wonderful 2213191Smckusick * program statement! 2223191Smckusick */ 2233191Smckusick # ifdef OBJ 2243191Smckusick if (monflg) { 2253191Smckusick put(1, O_PXPBUF); 2263191Smckusick cntpatch = put(2, O_CASE4, (long)0); 2273191Smckusick nfppatch = put(2, O_CASE4, (long)0); 2283191Smckusick } 2293191Smckusick # endif OBJ 2303191Smckusick cp = p; 2313191Smckusick for (rl = r[3]; rl; rl = rl[2]) { 2323191Smckusick if (rl[1] == NIL) 2333191Smckusick continue; 2343191Smckusick dp = defnl(rl[1], VAR, 0, 0); 2353191Smckusick cp->chain = dp; 2363191Smckusick cp = dp; 2373191Smckusick } 2383191Smckusick } 2393191Smckusick /* 2403191Smckusick * Define a branch at 2413191Smckusick * the "entry point" of 2423191Smckusick * the prog/proc/func. 2433191Smckusick */ 2443191Smckusick p->entloc = getlab(); 2453191Smckusick if (monflg) { 2463191Smckusick bodycnts[ cbn ] = getcnt(); 2473191Smckusick p->value[ NL_CNTR ] = 0; 2483191Smckusick } 2493191Smckusick # ifdef OBJ 2503191Smckusick put(2, O_TRA4, (long)p->entloc); 2513191Smckusick # endif OBJ 2523191Smckusick # ifdef PTREE 2533191Smckusick { 2543191Smckusick pPointer PF = tCopy( r ); 2553191Smckusick 2563191Smckusick pSeize( PorFHeader[ nesting ] ); 2573191Smckusick if ( r[0] != T_PROG ) { 2583191Smckusick pPointer *PFs; 2593191Smckusick 2603191Smckusick PFs = &( pDEF( PorFHeader[ nesting ] ).PorFPFs ); 2613191Smckusick *PFs = ListAppend( *PFs , PF ); 2623191Smckusick } else { 2633191Smckusick pDEF( PorFHeader[ nesting ] ).GlobProg = PF; 2643191Smckusick } 2653191Smckusick pRelease( PorFHeader[ nesting ] ); 2663191Smckusick } 2673191Smckusick # endif PTREE 2683191Smckusick return (p); 2693191Smckusick } 2703302Smckusic 2713302Smckusic /* 2723302Smckusic * deal with the parameter declaration for a routine. 2733302Smckusic * p is the namelist entry of the routine. 2743302Smckusic * formalist is the parse tree for the parameter declaration. 2753302Smckusic * formalist [0] T_LISTPP 2763302Smckusic * [1] pointer to a formal 2773302Smckusic * [2] pointer to next formal 2783302Smckusic * for by-value or by-reference formals, the formal is 2793302Smckusic * formal [0] T_PVAL or T_PVAR 2803302Smckusic * [1] pointer to id_list 2813302Smckusic * [2] pointer to type (error if not typeid) 2823302Smckusic * for function and procedure formals, the formal is 2833302Smckusic * formal [0] T_PFUNC or T_PPROC 2843302Smckusic * [1] pointer to id_list (error if more than one) 2853302Smckusic * [2] pointer to type (error if not typeid, or proc) 2863302Smckusic * [3] pointer to formalist for this routine. 2873302Smckusic */ 2883302Smckusic fparams(p, formal) 2893302Smckusic register struct nl *p; 2903302Smckusic int *formal; 2913302Smckusic { 2923302Smckusic params(p, formal[3]); 2933302Smckusic p -> value[ NL_LINENO ] = formal[4]; 2943302Smckusic p -> ptr[ NL_FCHAIN ] = p -> chain; 2953302Smckusic p -> chain = NIL; 2963302Smckusic } 2973302Smckusic 2983302Smckusic params(p, formalist) 2993302Smckusic register struct nl *p; 3003302Smckusic int *formalist; 3013302Smckusic { 3023302Smckusic struct nl *chainp, *savedp; 3033302Smckusic struct nl *dp; 3043302Smckusic register int **formalp; /* an element of the formal list */ 3053302Smckusic register int *formal; /* a formal */ 3063302Smckusic int *typ, *idlist; 3073302Smckusic int w, o; 3083302Smckusic 3093302Smckusic /* 3103302Smckusic * Enter the parameters 3113302Smckusic * and compute total size 3123302Smckusic */ 3133302Smckusic chainp = savedp = p; 3143302Smckusic 3153302Smckusic # ifdef OBJ 3163302Smckusic o = 0; 3173302Smckusic # endif OBJ 3183302Smckusic # ifdef PC 3193302Smckusic /* 3203302Smckusic * parameters used to be allocated backwards, 3213302Smckusic * then fixed. for pc, they are allocated correctly. 3223302Smckusic * also, they are aligned. 3233302Smckusic */ 3243302Smckusic o = DPOFF2; 3253302Smckusic # endif PC 3263302Smckusic for (formalp = formalist; formalp != NIL; formalp = formalp[2]) { 3273302Smckusic p = NIL; 3283302Smckusic formal = formalp[1]; 3293302Smckusic if (formal == NIL) 3303302Smckusic continue; 3313302Smckusic /* 3323302Smckusic * Parametric procedures 3333302Smckusic * don't have types !?! 3343302Smckusic */ 3353302Smckusic typ = formal[2]; 3363302Smckusic if ( typ == NIL ) { 3373302Smckusic if ( formal[0] != T_PPROC ) { 3383302Smckusic error("Types must be specified for arguments"); 3393302Smckusic p = NIL; 3403302Smckusic } 3413302Smckusic } else { 3423302Smckusic if ( formal[0] == T_PPROC ) { 3433302Smckusic error("Procedures cannot have types"); 3443302Smckusic p = NIL; 3453302Smckusic } else { 3463302Smckusic if (typ[0] != T_TYID) { 3473302Smckusic error("Types for arguments can be specified only by using type identifiers"); 3483302Smckusic p = NIL; 3493302Smckusic } else { 3503302Smckusic p = gtype(typ); 3513302Smckusic } 3523302Smckusic } 3533302Smckusic } 3543302Smckusic for (idlist = formal[1]; idlist != NIL; idlist = idlist[2]) { 3553302Smckusic switch (formal[0]) { 3563302Smckusic default: 3573302Smckusic panic("funchdr2"); 3583302Smckusic case T_PVAL: 3593302Smckusic if (p != NIL) { 3603302Smckusic if (p->class == FILET) 3613302Smckusic error("Files cannot be passed by value"); 3623302Smckusic else if (p->nl_flags & NFILES) 3633302Smckusic error("Files cannot be a component of %ss passed by value", 3643302Smckusic nameof(p)); 3653302Smckusic } 3663302Smckusic # ifdef OBJ 3673302Smckusic w = lwidth(p); 3683302Smckusic o -= even(w); 3693302Smckusic # ifdef DEC11 3703302Smckusic dp = defnl(idlist[1], VAR, p, o); 3713302Smckusic # else 3723302Smckusic dp = defnl(idlist[1], VAR, p, 3733302Smckusic (w < 2) ? o + 1 : o); 3743302Smckusic # endif DEC11 3753302Smckusic # endif OBJ 3763302Smckusic # ifdef PC 3773302Smckusic dp = defnl( idlist[1] , VAR , p 3783302Smckusic , o = roundup( o , (long)A_STACK ) ); 3793302Smckusic o += lwidth( p ); 3803302Smckusic # endif PC 3813302Smckusic dp->nl_flags |= NMOD; 3823302Smckusic break; 3833302Smckusic case T_PVAR: 3843302Smckusic # ifdef OBJ 3853302Smckusic dp = defnl(idlist[1], REF, p, o -= sizeof ( int * ) ); 3863302Smckusic # endif OBJ 3873302Smckusic # ifdef PC 3883302Smckusic dp = defnl( idlist[1] , REF , p 3893302Smckusic , o = roundup( o , (long)A_STACK ) ); 3903302Smckusic o += sizeof(char *); 3913302Smckusic # endif PC 3923302Smckusic break; 3933302Smckusic case T_PFUNC: 3943302Smckusic if (idlist[2] != NIL) { 3953302Smckusic error("Each function argument must be declared separately"); 3963302Smckusic idlist[2] = NIL; 3973302Smckusic } 3983302Smckusic # ifdef OBJ 3993302Smckusic dp = defnl(idlist[1], FFUNC, p, o -= sizeof ( int * ) ); 4003302Smckusic # endif OBJ 4013302Smckusic # ifdef PC 4023302Smckusic dp = defnl( idlist[1] , FFUNC , p 4033302Smckusic , o = roundup( o , (long)A_STACK ) ); 4043302Smckusic o += sizeof(char *); 4053302Smckusic # endif PC 4063302Smckusic dp -> nl_flags |= NMOD; 4073302Smckusic fparams(dp, formal); 4083302Smckusic break; 4093302Smckusic case T_PPROC: 4103302Smckusic if (idlist[2] != NIL) { 4113302Smckusic error("Each procedure argument must be declared separately"); 4123302Smckusic idlist[2] = NIL; 4133302Smckusic } 4143302Smckusic # ifdef OBJ 4153302Smckusic dp = defnl(idlist[1], FPROC, p, o -= sizeof ( int * ) ); 4163302Smckusic # endif OBJ 4173302Smckusic # ifdef PC 4183302Smckusic dp = defnl( idlist[1] , FPROC , p 4193302Smckusic , o = roundup( o , (long)A_STACK ) ); 4203302Smckusic o += sizeof(char *); 4213302Smckusic # endif PC 4223302Smckusic dp -> nl_flags |= NMOD; 4233302Smckusic fparams(dp, formal); 4243302Smckusic break; 4253302Smckusic } 4263302Smckusic if (dp != NIL) { 4273838Speter # ifdef PC 4283838Speter dp -> extra_flags |= NPARAM; 4293838Speter # endif PC 4303302Smckusic chainp->chain = dp; 4313302Smckusic chainp = dp; 4323302Smckusic } 4333302Smckusic } 4343302Smckusic } 4353302Smckusic p = savedp; 4363302Smckusic # ifdef OBJ 4373302Smckusic /* 4383302Smckusic * Correct the naivete (naivety) 4393302Smckusic * of our above code to 4403302Smckusic * calculate offsets 4413302Smckusic */ 4423302Smckusic for (dp = p->chain; dp != NIL; dp = dp->chain) 4433302Smckusic dp->value[NL_OFFS] += -o + DPOFF2; 4443302Smckusic return (-o + DPOFF2); 4453302Smckusic # endif OBJ 4463302Smckusic # ifdef PC 4473302Smckusic return roundup( o , (long)A_STACK ); 4483302Smckusic # endif PC 4493302Smckusic } 450