13191Smckusick /* Copyright (c) 1979 Regents of the University of California */ 23191Smckusick 314731Sthien #ifndef lint 4*18136Smckusick static char sccsid[] = "@(#)fhdr.c 2.2 02/28/85"; 514731Sthien #endif 63191Smckusick 73191Smckusick #include "whoami.h" 83191Smckusick #include "0.h" 93191Smckusick #include "tree.h" 103191Smckusick #include "opcode.h" 113191Smckusick #include "objfmt.h" 123191Smckusick #include "align.h" 1314731Sthien #include "tree_ty.h" 143191Smckusick 153191Smckusick /* 163191Smckusick * this array keeps the pxp counters associated with 173191Smckusick * functions and procedures, so that they can be output 183191Smckusick * when their bodies are encountered 193191Smckusick */ 203191Smckusick int bodycnts[ DSPLYSZ ]; 213191Smckusick 223191Smckusick #ifdef PC 233191Smckusick # include "pc.h" 243191Smckusick # include "pcops.h" 253191Smckusick #endif PC 263191Smckusick 273191Smckusick #ifdef OBJ 283191Smckusick int cntpatch; 293191Smckusick int nfppatch; 303191Smckusick #endif OBJ 313191Smckusick 323191Smckusick /* 333191Smckusick * Funchdr inserts 343191Smckusick * declaration of a the 353191Smckusick * prog/proc/func into the 363191Smckusick * namelist. It also handles 373191Smckusick * the arguments and puts out 383191Smckusick * a transfer which defines 393191Smckusick * the entry point of a procedure. 403191Smckusick */ 413191Smckusick 423191Smckusick struct nl * 433191Smckusick funchdr(r) 4414731Sthien struct tnode *r; 453191Smckusick { 463191Smckusick register struct nl *p; 4714731Sthien register struct tnode *rl; 4814731Sthien struct nl *cp, *dp, *temp; 4914731Sthien int o; 503191Smckusick 5114731Sthien if (inpflist(r->p_dec.id_ptr)) { 523191Smckusick opush('l'); 533191Smckusick yyretrieve(); /* kludge */ 543191Smckusick } 553191Smckusick pfcnt++; 563191Smckusick parts[ cbn ] |= RPRT; 5714731Sthien line = r->p_dec.line_no; 5814731Sthien if (r->p_dec.param_list == TR_NIL && 5914731Sthien (p=lookup1(r->p_dec.id_ptr)) != NIL && bn == cbn) { 603191Smckusick /* 613191Smckusick * Symbol already defined 623191Smckusick * in this block. it is either 633191Smckusick * a redeclared symbol (error) 643191Smckusick * a forward declaration, 653191Smckusick * or an external declaration. 667589Speter * check that forwards are of the right kind: 677589Speter * if this fails, we are trying to redefine it 687589Speter * and enter() will complain. 693191Smckusick */ 707589Speter if ( ( ( p->nl_flags & NFORWD ) != 0 ) 7114731Sthien && ( ( p->class == FUNC && r->tag == T_FDEC ) 7214731Sthien || ( p->class == PROC && r->tag == T_PDEC ) ) ) { 733191Smckusick /* 743191Smckusick * Grammar doesnt forbid 753191Smckusick * types on a resolution 763191Smckusick * of a forward function 773191Smckusick * declaration. 783191Smckusick */ 7914731Sthien if (p->class == FUNC && r->p_dec.type) 803191Smckusick error("Function type should be given only in forward declaration"); 813191Smckusick /* 823191Smckusick * get another counter for the actual 833191Smckusick */ 843191Smckusick if ( monflg ) { 853191Smckusick bodycnts[ cbn ] = getcnt(); 863191Smckusick } 873191Smckusick # ifdef PC 883191Smckusick enclosing[ cbn ] = p -> symbol; 893191Smckusick # endif PC 903191Smckusick # ifdef PTREE 913191Smckusick /* 923191Smckusick * mark this proc/func as forward 933191Smckusick * in the pTree. 943191Smckusick */ 953191Smckusick pDEF( p -> inTree ).PorFForward = TRUE; 963191Smckusick # endif PTREE 973191Smckusick return (p); 983191Smckusick } 993191Smckusick } 1003191Smckusick 1013191Smckusick /* if a routine segment is being compiled, 1023191Smckusick * do level one processing. 1033191Smckusick */ 1043191Smckusick 10514731Sthien if ((r->tag != T_PROG) && (!progseen)) 1063191Smckusick level1(); 1073191Smckusick 1083191Smckusick 1093191Smckusick /* 1103191Smckusick * Declare the prog/proc/func 1113191Smckusick */ 11214731Sthien switch (r->tag) { 1133191Smckusick case T_PROG: 1143191Smckusick progseen = TRUE; 1153191Smckusick if (opt('z')) 1163191Smckusick monflg = TRUE; 11714731Sthien program = p = defnl(r->p_dec.id_ptr, PROG, NLNIL, 0); 11814731Sthien p->value[3] = r->p_dec.line_no; 1193191Smckusick break; 1203191Smckusick case T_PDEC: 12114731Sthien if (r->p_dec.type != TR_NIL) 1223191Smckusick error("Procedures do not have types, only functions do"); 12314731Sthien p = enter(defnl(r->p_dec.id_ptr, PROC, NLNIL, 0)); 1243191Smckusick p->nl_flags |= NMOD; 1253191Smckusick # ifdef PC 12614731Sthien enclosing[ cbn ] = r->p_dec.id_ptr; 1273838Speter p -> extra_flags |= NGLOBAL; 1283191Smckusick # endif PC 1293191Smckusick break; 1303191Smckusick case T_FDEC: 13114731Sthien { 13214731Sthien register struct tnode *il; 13314731Sthien il = r->p_dec.type; 134*18136Smckusick if (il == TR_NIL) { 135*18136Smckusick temp = NLNIL; 1363191Smckusick error("Function type must be specified"); 137*18136Smckusick } else if (il->tag != T_TYID) { 13814731Sthien temp = NLNIL; 1393191Smckusick error("Function type can be specified only by using a type identifier"); 1403191Smckusick } else 14114731Sthien temp = gtype(il); 14214731Sthien } 143*18136Smckusick p = enter(defnl(r->p_dec.id_ptr, FUNC, temp, NIL)); 1443191Smckusick p->nl_flags |= NMOD; 1453191Smckusick /* 1463191Smckusick * An arbitrary restriction 1473191Smckusick */ 1483191Smckusick switch (o = classify(p->type)) { 1493191Smckusick case TFILE: 1503191Smckusick case TARY: 1513191Smckusick case TREC: 1523191Smckusick case TSET: 1533191Smckusick case TSTR: 1543191Smckusick warning(); 1553191Smckusick if (opt('s')) { 1563191Smckusick standard(); 1573191Smckusick } 1583191Smckusick error("Functions should not return %ss", clnames[o]); 1593191Smckusick } 1603191Smckusick # ifdef PC 16114731Sthien enclosing[ cbn ] = r->p_dec.id_ptr; 1623838Speter p -> extra_flags |= NGLOBAL; 1633191Smckusick # endif PC 1643191Smckusick break; 1653191Smckusick default: 1663191Smckusick panic("funchdr"); 1673191Smckusick } 16814731Sthien if (r->tag != T_PROG) { 1693191Smckusick /* 1703191Smckusick * Mark this proc/func as 1713191Smckusick * being forward declared 1723191Smckusick */ 1733191Smckusick p->nl_flags |= NFORWD; 1743191Smckusick /* 1753191Smckusick * Enter the parameters 1763191Smckusick * in the next block for 1773191Smckusick * the time being 1783191Smckusick */ 1793191Smckusick if (++cbn >= DSPLYSZ) { 1803191Smckusick error("Procedure/function nesting too deep"); 1813191Smckusick pexit(ERRS); 1823191Smckusick } 1833191Smckusick /* 1843191Smckusick * For functions, the function variable 1853191Smckusick */ 1863191Smckusick if (p->class == FUNC) { 1873191Smckusick # ifdef OBJ 18814731Sthien cp = defnl(r->p_dec.id_ptr, FVAR, p->type, 0); 1893191Smckusick # endif OBJ 1903191Smckusick # ifdef PC 1913191Smckusick /* 1923191Smckusick * fvars used to be allocated and deallocated 1933191Smckusick * by the caller right before the arguments. 1943191Smckusick * the offset of the fvar was kept in 1953191Smckusick * value[NL_OFFS] of function (very wierd, 1963191Smckusick * but see asgnop). 1973191Smckusick * now, they are locals to the function 1983191Smckusick * with the offset kept in the fvar. 1993191Smckusick */ 2003191Smckusick 20114731Sthien cp = defnl(r->p_dec.id_ptr, FVAR, p->type, 2023302Smckusic (int)-leven(roundup( 2033302Smckusic (int)(DPOFF1+lwidth(p->type)), 2043302Smckusic (long)align(p->type)))); 2053838Speter cp -> extra_flags |= NLOCAL; 2063191Smckusick # endif PC 2073191Smckusick cp->chain = p; 2083191Smckusick p->ptr[NL_FVAR] = cp; 2093191Smckusick } 2103191Smckusick /* 2113191Smckusick * Enter the parameters 2123191Smckusick * and compute total size 2133191Smckusick */ 21414731Sthien p->value[NL_OFFS] = params(p, r->p_dec.param_list); 2153302Smckusic /* 2163302Smckusic * because NL_LINENO field in the function 2173302Smckusic * namelist entry has been used (as have all 2183302Smckusic * the other fields), the line number is 2193302Smckusic * stored in the NL_LINENO field of its fvar. 2203302Smckusic */ 2213302Smckusic if (p->class == FUNC) 22214731Sthien p->ptr[NL_FVAR]->value[NL_LINENO] = r->p_dec.line_no; 2233302Smckusic else 22414731Sthien p->value[NL_LINENO] = r->p_dec.line_no; 2253191Smckusick cbn--; 2263191Smckusick } else { 2273191Smckusick /* 2283191Smckusick * The wonderful 2293191Smckusick * program statement! 2303191Smckusick */ 2313191Smckusick # ifdef OBJ 2323191Smckusick if (monflg) { 23314731Sthien (void) put(1, O_PXPBUF); 2343191Smckusick cntpatch = put(2, O_CASE4, (long)0); 2353191Smckusick nfppatch = put(2, O_CASE4, (long)0); 2363191Smckusick } 2373191Smckusick # endif OBJ 2383191Smckusick cp = p; 23914731Sthien for (rl = r->p_dec.param_list; rl; rl = rl->list_node.next) { 24014731Sthien if (rl->list_node.list == TR_NIL) 2413191Smckusick continue; 24214731Sthien dp = defnl((char *) rl->list_node.list, VAR, NLNIL, 0); 2433191Smckusick cp->chain = dp; 2443191Smckusick cp = dp; 2453191Smckusick } 2463191Smckusick } 2473191Smckusick /* 2483191Smckusick * Define a branch at 2493191Smckusick * the "entry point" of 2503191Smckusick * the prog/proc/func. 2513191Smckusick */ 25214731Sthien p->value[NL_ENTLOC] = (int) getlab(); 2533191Smckusick if (monflg) { 2543191Smckusick bodycnts[ cbn ] = getcnt(); 2553191Smckusick p->value[ NL_CNTR ] = 0; 2563191Smckusick } 2573191Smckusick # ifdef OBJ 25814731Sthien (void) put(2, O_TRA4, (long)p->value[NL_ENTLOC]); 2593191Smckusick # endif OBJ 2603191Smckusick # ifdef PTREE 2613191Smckusick { 2623191Smckusick pPointer PF = tCopy( r ); 2633191Smckusick 2643191Smckusick pSeize( PorFHeader[ nesting ] ); 26514731Sthien if ( r->tag != T_PROG ) { 2663191Smckusick pPointer *PFs; 2673191Smckusick 2683191Smckusick PFs = &( pDEF( PorFHeader[ nesting ] ).PorFPFs ); 2693191Smckusick *PFs = ListAppend( *PFs , PF ); 2703191Smckusick } else { 2713191Smckusick pDEF( PorFHeader[ nesting ] ).GlobProg = PF; 2723191Smckusick } 2733191Smckusick pRelease( PorFHeader[ nesting ] ); 2743191Smckusick } 2753191Smckusick # endif PTREE 2763191Smckusick return (p); 2773191Smckusick } 2783302Smckusic 2793302Smckusic /* 2803302Smckusic * deal with the parameter declaration for a routine. 2813302Smckusic * p is the namelist entry of the routine. 2823302Smckusic * formalist is the parse tree for the parameter declaration. 2833302Smckusic * formalist [0] T_LISTPP 2843302Smckusic * [1] pointer to a formal 2853302Smckusic * [2] pointer to next formal 2863302Smckusic * for by-value or by-reference formals, the formal is 2873302Smckusic * formal [0] T_PVAL or T_PVAR 2883302Smckusic * [1] pointer to id_list 2893302Smckusic * [2] pointer to type (error if not typeid) 2903302Smckusic * for function and procedure formals, the formal is 2913302Smckusic * formal [0] T_PFUNC or T_PPROC 2923302Smckusic * [1] pointer to id_list (error if more than one) 2933302Smckusic * [2] pointer to type (error if not typeid, or proc) 2943302Smckusic * [3] pointer to formalist for this routine. 2953302Smckusic */ 2963302Smckusic fparams(p, formal) 2973302Smckusic register struct nl *p; 29814731Sthien struct tnode *formal; /* T_PFUNC or T_PPROC */ 2993302Smckusic { 30014731Sthien (void) params(p, formal->pfunc_node.param_list); 30114731Sthien p -> value[ NL_LINENO ] = formal->pfunc_node.line_no; 3023302Smckusic p -> ptr[ NL_FCHAIN ] = p -> chain; 3033302Smckusic p -> chain = NIL; 3043302Smckusic } 3053302Smckusic 3063302Smckusic params(p, formalist) 3073302Smckusic register struct nl *p; 30814731Sthien struct tnode *formalist; /* T_LISTPP */ 3093302Smckusic { 3103302Smckusic struct nl *chainp, *savedp; 3113302Smckusic struct nl *dp; 31214731Sthien register struct tnode *formalp; /* an element of the formal list */ 31314731Sthien register struct tnode *formal; /* a formal */ 31415969Smckusick struct tnode *r, *s, *t, *typ, *idlist; 3153302Smckusic int w, o; 3163302Smckusic 3173302Smckusic /* 3183302Smckusic * Enter the parameters 3193302Smckusic * and compute total size 3203302Smckusic */ 3213302Smckusic chainp = savedp = p; 3223302Smckusic 3233302Smckusic # ifdef OBJ 3243302Smckusic o = 0; 3253302Smckusic # endif OBJ 3263302Smckusic # ifdef PC 3273302Smckusic /* 3283302Smckusic * parameters used to be allocated backwards, 3293302Smckusic * then fixed. for pc, they are allocated correctly. 3303302Smckusic * also, they are aligned. 3313302Smckusic */ 3323302Smckusic o = DPOFF2; 3333302Smckusic # endif PC 33414731Sthien for (formalp = formalist; formalp != TR_NIL; 33514731Sthien formalp = formalp->list_node.next) { 33614731Sthien p = NLNIL; 33714731Sthien formal = formalp->list_node.list; 33814731Sthien if (formal == TR_NIL) 3393302Smckusic continue; 3403302Smckusic /* 3413302Smckusic * Parametric procedures 3423302Smckusic * don't have types !?! 3433302Smckusic */ 34414731Sthien typ = formal->pfunc_node.type; 34514731Sthien if ( typ == TR_NIL ) { 34614731Sthien if ( formal->tag != T_PPROC ) { 3473302Smckusic error("Types must be specified for arguments"); 34814731Sthien p = NLNIL; 3493302Smckusic } 3503302Smckusic } else { 35114731Sthien if ( formal->tag == T_PPROC ) { 3523302Smckusic error("Procedures cannot have types"); 35314731Sthien p = NLNIL; 3543302Smckusic } else { 35515969Smckusick p = gtype(typ); 3563302Smckusic } 3573302Smckusic } 35814731Sthien for (idlist = formal->param.id_list; idlist != TR_NIL; 35914731Sthien idlist = idlist->list_node.next) { 36014731Sthien switch (formal->tag) { 3613302Smckusic default: 3623302Smckusic panic("funchdr2"); 3633302Smckusic case T_PVAL: 36414731Sthien if (p != NLNIL) { 3653302Smckusic if (p->class == FILET) 3663302Smckusic error("Files cannot be passed by value"); 3673302Smckusic else if (p->nl_flags & NFILES) 3683302Smckusic error("Files cannot be a component of %ss passed by value", 3693302Smckusic nameof(p)); 3703302Smckusic } 3713302Smckusic # ifdef OBJ 3723302Smckusic w = lwidth(p); 3733302Smckusic o -= even(w); 3743302Smckusic # ifdef DEC11 37514731Sthien dp = defnl((char *) idlist->list_node.list, 37614731Sthien VAR, p, o); 3773302Smckusic # else 37814731Sthien dp = defnl((char *) idlist->list_node.list, 37914731Sthien VAR,p, (w < 2) ? o + 1 : o); 3803302Smckusic # endif DEC11 3813302Smckusic # endif OBJ 3823302Smckusic # ifdef PC 38314731Sthien o = roundup(o, (long) A_STACK); 38410654Speter w = lwidth(p); 38510654Speter # ifndef DEC11 38610654Speter if (w <= sizeof(int)) { 38710654Speter o += sizeof(int) - w; 38810654Speter } 38910654Speter # endif not DEC11 39014731Sthien dp = defnl((char *) idlist->list_node.list,VAR, 39114731Sthien p, o); 39210654Speter o += w; 3933302Smckusic # endif PC 3943302Smckusic dp->nl_flags |= NMOD; 3953302Smckusic break; 3963302Smckusic case T_PVAR: 3973302Smckusic # ifdef OBJ 39814731Sthien dp = defnl((char *) idlist->list_node.list, REF, 39914731Sthien p, o -= sizeof ( int * ) ); 4003302Smckusic # endif OBJ 4013302Smckusic # ifdef PC 40214731Sthien dp = defnl( (char *) idlist->list_node.list, REF, 40314731Sthien p , 40414731Sthien o = roundup( o , (long)A_STACK ) ); 4053302Smckusic o += sizeof(char *); 4063302Smckusic # endif PC 4073302Smckusic break; 4083302Smckusic case T_PFUNC: 40914731Sthien if (idlist->list_node.next != TR_NIL) { 4103302Smckusic error("Each function argument must be declared separately"); 41114731Sthien idlist->list_node.next = TR_NIL; 4123302Smckusic } 4133302Smckusic # ifdef OBJ 41414731Sthien dp = defnl((char *) idlist->list_node.list,FFUNC, 41514731Sthien p, o -= sizeof ( int * ) ); 4163302Smckusic # endif OBJ 4173302Smckusic # ifdef PC 41814731Sthien dp = defnl( (char *) idlist->list_node.list , 41914731Sthien FFUNC , p , 42014731Sthien o = roundup( o , (long)A_STACK ) ); 4213302Smckusic o += sizeof(char *); 4223302Smckusic # endif PC 4233302Smckusic dp -> nl_flags |= NMOD; 4243302Smckusic fparams(dp, formal); 4253302Smckusic break; 4263302Smckusic case T_PPROC: 42714731Sthien if (idlist->list_node.next != TR_NIL) { 4283302Smckusic error("Each procedure argument must be declared separately"); 42914731Sthien idlist->list_node.next = TR_NIL; 4303302Smckusic } 4313302Smckusic # ifdef OBJ 43214731Sthien dp = defnl((char *) idlist->list_node.list, 43314731Sthien FPROC, p, o -= sizeof ( int * ) ); 4343302Smckusic # endif OBJ 4353302Smckusic # ifdef PC 43614731Sthien dp = defnl( (char *) idlist->list_node.list , 43714731Sthien FPROC , p, 43814731Sthien o = roundup( o , (long)A_STACK ) ); 4393302Smckusic o += sizeof(char *); 4403302Smckusic # endif PC 4413302Smckusic dp -> nl_flags |= NMOD; 4423302Smckusic fparams(dp, formal); 4433302Smckusic break; 4443302Smckusic } 44514731Sthien if (dp != NLNIL) { 4463838Speter # ifdef PC 4473838Speter dp -> extra_flags |= NPARAM; 4483838Speter # endif PC 4493302Smckusic chainp->chain = dp; 4503302Smckusic chainp = dp; 4513302Smckusic } 4523302Smckusic } 45315969Smckusick if (typ->tag == T_TYCARY) { 45415969Smckusick # ifdef OBJ 45515969Smckusick w = -even(lwidth(p->chain)); 45615969Smckusick # ifndef DEC11 45715969Smckusick w = (w > -2)? w + 1 : w; 45815969Smckusick # endif 45915969Smckusick # endif OBJ 46015969Smckusick # ifdef PC 46115969Smckusick w = lwidth(p->chain); 46215969Smckusick o = roundup(o, (long)A_STACK); 46315969Smckusick # endif PC 46415969Smckusick /* 46515969Smckusick * Allocate space for upper and 46615969Smckusick * lower bounds and width. 46715969Smckusick */ 46815969Smckusick for (s=typ; s->tag == T_TYCARY; s = s->ary_ty.type) { 46915969Smckusick for (r=s->ary_ty.type_list; r != TR_NIL; 47015969Smckusick r = r->list_node.next) { 47115969Smckusick t = r->list_node.list; 47215969Smckusick p = p->chain; 47315969Smckusick # ifdef OBJ 47415969Smckusick o += w; 47515969Smckusick # endif OBJ 47615969Smckusick chainp->chain = defnl(t->crang_ty.lwb_var, 47715969Smckusick VAR, p, o); 47815969Smckusick chainp = chainp->chain; 47915969Smckusick chainp->nl_flags |= (NMOD | NUSED); 48015969Smckusick p->nptr[0] = chainp; 48115969Smckusick o += w; 48215969Smckusick chainp->chain = defnl(t->crang_ty.upb_var, 48315969Smckusick VAR, p, o); 48415969Smckusick chainp = chainp->chain; 48515969Smckusick chainp->nl_flags |= (NMOD | NUSED); 48615969Smckusick p->nptr[1] = chainp; 48715969Smckusick o += w; 48815969Smckusick chainp->chain = defnl(0, VAR, p, o); 48915969Smckusick chainp = chainp->chain; 49015969Smckusick chainp->nl_flags |= (NMOD | NUSED); 49115969Smckusick p->nptr[2] = chainp; 49215969Smckusick # ifdef PC 49315969Smckusick o += w; 49415969Smckusick # endif PC 49515969Smckusick } 49615969Smckusick } 49715969Smckusick } 4983302Smckusic } 4993302Smckusic p = savedp; 5003302Smckusic # ifdef OBJ 5013302Smckusic /* 5023302Smckusic * Correct the naivete (naivety) 5033302Smckusic * of our above code to 5043302Smckusic * calculate offsets 5053302Smckusic */ 50614731Sthien for (dp = p->chain; dp != NLNIL; dp = dp->chain) 5073302Smckusic dp->value[NL_OFFS] += -o + DPOFF2; 5083302Smckusic return (-o + DPOFF2); 5093302Smckusic # endif OBJ 5103302Smckusic # ifdef PC 5113302Smckusic return roundup( o , (long)A_STACK ); 5123302Smckusic # endif PC 5133302Smckusic } 514