13191Smckusick /* Copyright (c) 1979 Regents of the University of California */ 23191Smckusick 314731Sthien #ifndef lint 4*15969Smckusick static char sccsid[] = "@(#)fhdr.c 1.9 02/08/84"; 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; 13414731Sthien if (il == TR_NIL) 1353191Smckusick error("Function type must be specified"); 13614731Sthien else if (il->tag != T_TYID) { 13714731Sthien temp = NLNIL; 1383191Smckusick error("Function type can be specified only by using a type identifier"); 1393191Smckusick } else 14014731Sthien temp = gtype(il); 14114731Sthien } 14214731Sthien { 14314731Sthien register struct nl *il; 14414731Sthien 14514731Sthien il = temp; 14614731Sthien p = enter(defnl(r->p_dec.id_ptr, FUNC, il, NIL)); 14714731Sthien 14814731Sthien } 14914731Sthien 1503191Smckusick p->nl_flags |= NMOD; 1513191Smckusick /* 1523191Smckusick * An arbitrary restriction 1533191Smckusick */ 1543191Smckusick switch (o = classify(p->type)) { 1553191Smckusick case TFILE: 1563191Smckusick case TARY: 1573191Smckusick case TREC: 1583191Smckusick case TSET: 1593191Smckusick case TSTR: 1603191Smckusick warning(); 1613191Smckusick if (opt('s')) { 1623191Smckusick standard(); 1633191Smckusick } 1643191Smckusick error("Functions should not return %ss", clnames[o]); 1653191Smckusick } 1663191Smckusick # ifdef PC 16714731Sthien enclosing[ cbn ] = r->p_dec.id_ptr; 1683838Speter p -> extra_flags |= NGLOBAL; 1693191Smckusick # endif PC 1703191Smckusick break; 1713191Smckusick default: 1723191Smckusick panic("funchdr"); 1733191Smckusick } 17414731Sthien if (r->tag != T_PROG) { 1753191Smckusick /* 1763191Smckusick * Mark this proc/func as 1773191Smckusick * being forward declared 1783191Smckusick */ 1793191Smckusick p->nl_flags |= NFORWD; 1803191Smckusick /* 1813191Smckusick * Enter the parameters 1823191Smckusick * in the next block for 1833191Smckusick * the time being 1843191Smckusick */ 1853191Smckusick if (++cbn >= DSPLYSZ) { 1863191Smckusick error("Procedure/function nesting too deep"); 1873191Smckusick pexit(ERRS); 1883191Smckusick } 1893191Smckusick /* 1903191Smckusick * For functions, the function variable 1913191Smckusick */ 1923191Smckusick if (p->class == FUNC) { 1933191Smckusick # ifdef OBJ 19414731Sthien cp = defnl(r->p_dec.id_ptr, FVAR, p->type, 0); 1953191Smckusick # endif OBJ 1963191Smckusick # ifdef PC 1973191Smckusick /* 1983191Smckusick * fvars used to be allocated and deallocated 1993191Smckusick * by the caller right before the arguments. 2003191Smckusick * the offset of the fvar was kept in 2013191Smckusick * value[NL_OFFS] of function (very wierd, 2023191Smckusick * but see asgnop). 2033191Smckusick * now, they are locals to the function 2043191Smckusick * with the offset kept in the fvar. 2053191Smckusick */ 2063191Smckusick 20714731Sthien cp = defnl(r->p_dec.id_ptr, FVAR, p->type, 2083302Smckusic (int)-leven(roundup( 2093302Smckusic (int)(DPOFF1+lwidth(p->type)), 2103302Smckusic (long)align(p->type)))); 2113838Speter cp -> extra_flags |= NLOCAL; 2123191Smckusick # endif PC 2133191Smckusick cp->chain = p; 2143191Smckusick p->ptr[NL_FVAR] = cp; 2153191Smckusick } 2163191Smckusick /* 2173191Smckusick * Enter the parameters 2183191Smckusick * and compute total size 2193191Smckusick */ 22014731Sthien p->value[NL_OFFS] = params(p, r->p_dec.param_list); 2213302Smckusic /* 2223302Smckusic * because NL_LINENO field in the function 2233302Smckusic * namelist entry has been used (as have all 2243302Smckusic * the other fields), the line number is 2253302Smckusic * stored in the NL_LINENO field of its fvar. 2263302Smckusic */ 2273302Smckusic if (p->class == FUNC) 22814731Sthien p->ptr[NL_FVAR]->value[NL_LINENO] = r->p_dec.line_no; 2293302Smckusic else 23014731Sthien p->value[NL_LINENO] = r->p_dec.line_no; 2313191Smckusick cbn--; 2323191Smckusick } else { 2333191Smckusick /* 2343191Smckusick * The wonderful 2353191Smckusick * program statement! 2363191Smckusick */ 2373191Smckusick # ifdef OBJ 2383191Smckusick if (monflg) { 23914731Sthien (void) put(1, O_PXPBUF); 2403191Smckusick cntpatch = put(2, O_CASE4, (long)0); 2413191Smckusick nfppatch = put(2, O_CASE4, (long)0); 2423191Smckusick } 2433191Smckusick # endif OBJ 2443191Smckusick cp = p; 24514731Sthien for (rl = r->p_dec.param_list; rl; rl = rl->list_node.next) { 24614731Sthien if (rl->list_node.list == TR_NIL) 2473191Smckusick continue; 24814731Sthien dp = defnl((char *) rl->list_node.list, VAR, NLNIL, 0); 2493191Smckusick cp->chain = dp; 2503191Smckusick cp = dp; 2513191Smckusick } 2523191Smckusick } 2533191Smckusick /* 2543191Smckusick * Define a branch at 2553191Smckusick * the "entry point" of 2563191Smckusick * the prog/proc/func. 2573191Smckusick */ 25814731Sthien p->value[NL_ENTLOC] = (int) getlab(); 2593191Smckusick if (monflg) { 2603191Smckusick bodycnts[ cbn ] = getcnt(); 2613191Smckusick p->value[ NL_CNTR ] = 0; 2623191Smckusick } 2633191Smckusick # ifdef OBJ 26414731Sthien (void) put(2, O_TRA4, (long)p->value[NL_ENTLOC]); 2653191Smckusick # endif OBJ 2663191Smckusick # ifdef PTREE 2673191Smckusick { 2683191Smckusick pPointer PF = tCopy( r ); 2693191Smckusick 2703191Smckusick pSeize( PorFHeader[ nesting ] ); 27114731Sthien if ( r->tag != T_PROG ) { 2723191Smckusick pPointer *PFs; 2733191Smckusick 2743191Smckusick PFs = &( pDEF( PorFHeader[ nesting ] ).PorFPFs ); 2753191Smckusick *PFs = ListAppend( *PFs , PF ); 2763191Smckusick } else { 2773191Smckusick pDEF( PorFHeader[ nesting ] ).GlobProg = PF; 2783191Smckusick } 2793191Smckusick pRelease( PorFHeader[ nesting ] ); 2803191Smckusick } 2813191Smckusick # endif PTREE 2823191Smckusick return (p); 2833191Smckusick } 2843302Smckusic 2853302Smckusic /* 2863302Smckusic * deal with the parameter declaration for a routine. 2873302Smckusic * p is the namelist entry of the routine. 2883302Smckusic * formalist is the parse tree for the parameter declaration. 2893302Smckusic * formalist [0] T_LISTPP 2903302Smckusic * [1] pointer to a formal 2913302Smckusic * [2] pointer to next formal 2923302Smckusic * for by-value or by-reference formals, the formal is 2933302Smckusic * formal [0] T_PVAL or T_PVAR 2943302Smckusic * [1] pointer to id_list 2953302Smckusic * [2] pointer to type (error if not typeid) 2963302Smckusic * for function and procedure formals, the formal is 2973302Smckusic * formal [0] T_PFUNC or T_PPROC 2983302Smckusic * [1] pointer to id_list (error if more than one) 2993302Smckusic * [2] pointer to type (error if not typeid, or proc) 3003302Smckusic * [3] pointer to formalist for this routine. 3013302Smckusic */ 3023302Smckusic fparams(p, formal) 3033302Smckusic register struct nl *p; 30414731Sthien struct tnode *formal; /* T_PFUNC or T_PPROC */ 3053302Smckusic { 30614731Sthien (void) params(p, formal->pfunc_node.param_list); 30714731Sthien p -> value[ NL_LINENO ] = formal->pfunc_node.line_no; 3083302Smckusic p -> ptr[ NL_FCHAIN ] = p -> chain; 3093302Smckusic p -> chain = NIL; 3103302Smckusic } 3113302Smckusic 3123302Smckusic params(p, formalist) 3133302Smckusic register struct nl *p; 31414731Sthien struct tnode *formalist; /* T_LISTPP */ 3153302Smckusic { 3163302Smckusic struct nl *chainp, *savedp; 3173302Smckusic struct nl *dp; 31814731Sthien register struct tnode *formalp; /* an element of the formal list */ 31914731Sthien register struct tnode *formal; /* a formal */ 320*15969Smckusick struct tnode *r, *s, *t, *typ, *idlist; 3213302Smckusic int w, o; 3223302Smckusic 3233302Smckusic /* 3243302Smckusic * Enter the parameters 3253302Smckusic * and compute total size 3263302Smckusic */ 3273302Smckusic chainp = savedp = p; 3283302Smckusic 3293302Smckusic # ifdef OBJ 3303302Smckusic o = 0; 3313302Smckusic # endif OBJ 3323302Smckusic # ifdef PC 3333302Smckusic /* 3343302Smckusic * parameters used to be allocated backwards, 3353302Smckusic * then fixed. for pc, they are allocated correctly. 3363302Smckusic * also, they are aligned. 3373302Smckusic */ 3383302Smckusic o = DPOFF2; 3393302Smckusic # endif PC 34014731Sthien for (formalp = formalist; formalp != TR_NIL; 34114731Sthien formalp = formalp->list_node.next) { 34214731Sthien p = NLNIL; 34314731Sthien formal = formalp->list_node.list; 34414731Sthien if (formal == TR_NIL) 3453302Smckusic continue; 3463302Smckusic /* 3473302Smckusic * Parametric procedures 3483302Smckusic * don't have types !?! 3493302Smckusic */ 35014731Sthien typ = formal->pfunc_node.type; 35114731Sthien if ( typ == TR_NIL ) { 35214731Sthien if ( formal->tag != T_PPROC ) { 3533302Smckusic error("Types must be specified for arguments"); 35414731Sthien p = NLNIL; 3553302Smckusic } 3563302Smckusic } else { 35714731Sthien if ( formal->tag == T_PPROC ) { 3583302Smckusic error("Procedures cannot have types"); 35914731Sthien p = NLNIL; 3603302Smckusic } else { 361*15969Smckusick p = gtype(typ); 3623302Smckusic } 3633302Smckusic } 36414731Sthien for (idlist = formal->param.id_list; idlist != TR_NIL; 36514731Sthien idlist = idlist->list_node.next) { 36614731Sthien switch (formal->tag) { 3673302Smckusic default: 3683302Smckusic panic("funchdr2"); 3693302Smckusic case T_PVAL: 37014731Sthien if (p != NLNIL) { 3713302Smckusic if (p->class == FILET) 3723302Smckusic error("Files cannot be passed by value"); 3733302Smckusic else if (p->nl_flags & NFILES) 3743302Smckusic error("Files cannot be a component of %ss passed by value", 3753302Smckusic nameof(p)); 3763302Smckusic } 3773302Smckusic # ifdef OBJ 3783302Smckusic w = lwidth(p); 3793302Smckusic o -= even(w); 3803302Smckusic # ifdef DEC11 38114731Sthien dp = defnl((char *) idlist->list_node.list, 38214731Sthien VAR, p, o); 3833302Smckusic # else 38414731Sthien dp = defnl((char *) idlist->list_node.list, 38514731Sthien VAR,p, (w < 2) ? o + 1 : o); 3863302Smckusic # endif DEC11 3873302Smckusic # endif OBJ 3883302Smckusic # ifdef PC 38914731Sthien o = roundup(o, (long) A_STACK); 39010654Speter w = lwidth(p); 39110654Speter # ifndef DEC11 39210654Speter if (w <= sizeof(int)) { 39310654Speter o += sizeof(int) - w; 39410654Speter } 39510654Speter # endif not DEC11 39614731Sthien dp = defnl((char *) idlist->list_node.list,VAR, 39714731Sthien p, o); 39810654Speter o += w; 3993302Smckusic # endif PC 4003302Smckusic dp->nl_flags |= NMOD; 4013302Smckusic break; 4023302Smckusic case T_PVAR: 4033302Smckusic # ifdef OBJ 40414731Sthien dp = defnl((char *) idlist->list_node.list, REF, 40514731Sthien p, o -= sizeof ( int * ) ); 4063302Smckusic # endif OBJ 4073302Smckusic # ifdef PC 40814731Sthien dp = defnl( (char *) idlist->list_node.list, REF, 40914731Sthien p , 41014731Sthien o = roundup( o , (long)A_STACK ) ); 4113302Smckusic o += sizeof(char *); 4123302Smckusic # endif PC 4133302Smckusic break; 4143302Smckusic case T_PFUNC: 41514731Sthien if (idlist->list_node.next != TR_NIL) { 4163302Smckusic error("Each function argument must be declared separately"); 41714731Sthien idlist->list_node.next = TR_NIL; 4183302Smckusic } 4193302Smckusic # ifdef OBJ 42014731Sthien dp = defnl((char *) idlist->list_node.list,FFUNC, 42114731Sthien p, o -= sizeof ( int * ) ); 4223302Smckusic # endif OBJ 4233302Smckusic # ifdef PC 42414731Sthien dp = defnl( (char *) idlist->list_node.list , 42514731Sthien FFUNC , p , 42614731Sthien o = roundup( o , (long)A_STACK ) ); 4273302Smckusic o += sizeof(char *); 4283302Smckusic # endif PC 4293302Smckusic dp -> nl_flags |= NMOD; 4303302Smckusic fparams(dp, formal); 4313302Smckusic break; 4323302Smckusic case T_PPROC: 43314731Sthien if (idlist->list_node.next != TR_NIL) { 4343302Smckusic error("Each procedure argument must be declared separately"); 43514731Sthien idlist->list_node.next = TR_NIL; 4363302Smckusic } 4373302Smckusic # ifdef OBJ 43814731Sthien dp = defnl((char *) idlist->list_node.list, 43914731Sthien FPROC, p, o -= sizeof ( int * ) ); 4403302Smckusic # endif OBJ 4413302Smckusic # ifdef PC 44214731Sthien dp = defnl( (char *) idlist->list_node.list , 44314731Sthien FPROC , p, 44414731Sthien o = roundup( o , (long)A_STACK ) ); 4453302Smckusic o += sizeof(char *); 4463302Smckusic # endif PC 4473302Smckusic dp -> nl_flags |= NMOD; 4483302Smckusic fparams(dp, formal); 4493302Smckusic break; 4503302Smckusic } 45114731Sthien if (dp != NLNIL) { 4523838Speter # ifdef PC 4533838Speter dp -> extra_flags |= NPARAM; 4543838Speter # endif PC 4553302Smckusic chainp->chain = dp; 4563302Smckusic chainp = dp; 4573302Smckusic } 4583302Smckusic } 459*15969Smckusick if (typ->tag == T_TYCARY) { 460*15969Smckusick # ifdef OBJ 461*15969Smckusick w = -even(lwidth(p->chain)); 462*15969Smckusick # ifndef DEC11 463*15969Smckusick w = (w > -2)? w + 1 : w; 464*15969Smckusick # endif 465*15969Smckusick # endif OBJ 466*15969Smckusick # ifdef PC 467*15969Smckusick w = lwidth(p->chain); 468*15969Smckusick o = roundup(o, (long)A_STACK); 469*15969Smckusick # endif PC 470*15969Smckusick /* 471*15969Smckusick * Allocate space for upper and 472*15969Smckusick * lower bounds and width. 473*15969Smckusick */ 474*15969Smckusick for (s=typ; s->tag == T_TYCARY; s = s->ary_ty.type) { 475*15969Smckusick for (r=s->ary_ty.type_list; r != TR_NIL; 476*15969Smckusick r = r->list_node.next) { 477*15969Smckusick t = r->list_node.list; 478*15969Smckusick p = p->chain; 479*15969Smckusick # ifdef OBJ 480*15969Smckusick o += w; 481*15969Smckusick # endif OBJ 482*15969Smckusick chainp->chain = defnl(t->crang_ty.lwb_var, 483*15969Smckusick VAR, p, o); 484*15969Smckusick chainp = chainp->chain; 485*15969Smckusick chainp->nl_flags |= (NMOD | NUSED); 486*15969Smckusick p->nptr[0] = chainp; 487*15969Smckusick o += w; 488*15969Smckusick chainp->chain = defnl(t->crang_ty.upb_var, 489*15969Smckusick VAR, p, o); 490*15969Smckusick chainp = chainp->chain; 491*15969Smckusick chainp->nl_flags |= (NMOD | NUSED); 492*15969Smckusick p->nptr[1] = chainp; 493*15969Smckusick o += w; 494*15969Smckusick chainp->chain = defnl(0, VAR, p, o); 495*15969Smckusick chainp = chainp->chain; 496*15969Smckusick chainp->nl_flags |= (NMOD | NUSED); 497*15969Smckusick p->nptr[2] = chainp; 498*15969Smckusick # ifdef PC 499*15969Smckusick o += w; 500*15969Smckusick # endif PC 501*15969Smckusick } 502*15969Smckusick } 503*15969Smckusick } 5043302Smckusic } 5053302Smckusic p = savedp; 5063302Smckusic # ifdef OBJ 5073302Smckusic /* 5083302Smckusic * Correct the naivete (naivety) 5093302Smckusic * of our above code to 5103302Smckusic * calculate offsets 5113302Smckusic */ 51214731Sthien for (dp = p->chain; dp != NLNIL; dp = dp->chain) 5133302Smckusic dp->value[NL_OFFS] += -o + DPOFF2; 5143302Smckusic return (-o + DPOFF2); 5153302Smckusic # endif OBJ 5163302Smckusic # ifdef PC 5173302Smckusic return roundup( o , (long)A_STACK ); 5183302Smckusic # endif PC 5193302Smckusic } 520