1*48116Sbostic /*- 2*48116Sbostic * Copyright (c) 1980 The Regents of the University of California. 3*48116Sbostic * All rights reserved. 4*48116Sbostic * 5*48116Sbostic * %sccs.include.redist.c% 622165Sdist */ 73191Smckusick 814731Sthien #ifndef lint 9*48116Sbostic static char sccsid[] = "@(#)fhdr.c 5.4 (Berkeley) 04/16/91"; 10*48116Sbostic #endif /* not lint */ 113191Smckusick 123191Smckusick #include "whoami.h" 133191Smckusick #include "0.h" 143191Smckusick #include "tree.h" 153191Smckusick #include "opcode.h" 163191Smckusick #include "objfmt.h" 173191Smckusick #include "align.h" 1814731Sthien #include "tree_ty.h" 193191Smckusick 203191Smckusick /* 213191Smckusick * this array keeps the pxp counters associated with 223191Smckusick * functions and procedures, so that they can be output 233191Smckusick * when their bodies are encountered 243191Smckusick */ 253191Smckusick int bodycnts[ DSPLYSZ ]; 263191Smckusick 273191Smckusick #ifdef PC 283191Smckusick # include "pc.h" 293191Smckusick #endif PC 303191Smckusick 313191Smckusick #ifdef OBJ 323191Smckusick int cntpatch; 333191Smckusick int nfppatch; 343191Smckusick #endif OBJ 353191Smckusick 363191Smckusick /* 373191Smckusick * Funchdr inserts 383191Smckusick * declaration of a the 393191Smckusick * prog/proc/func into the 403191Smckusick * namelist. It also handles 413191Smckusick * the arguments and puts out 423191Smckusick * a transfer which defines 433191Smckusick * the entry point of a procedure. 443191Smckusick */ 453191Smckusick 463191Smckusick struct nl * 473191Smckusick funchdr(r) 4814731Sthien struct tnode *r; 493191Smckusick { 503191Smckusick register struct nl *p; 5114731Sthien register struct tnode *rl; 5214731Sthien struct nl *cp, *dp, *temp; 5314731Sthien int o; 543191Smckusick 5514731Sthien if (inpflist(r->p_dec.id_ptr)) { 563191Smckusick opush('l'); 573191Smckusick yyretrieve(); /* kludge */ 583191Smckusick } 593191Smckusick pfcnt++; 603191Smckusick parts[ cbn ] |= RPRT; 6114731Sthien line = r->p_dec.line_no; 6214731Sthien if (r->p_dec.param_list == TR_NIL && 6314731Sthien (p=lookup1(r->p_dec.id_ptr)) != NIL && bn == cbn) { 643191Smckusick /* 653191Smckusick * Symbol already defined 663191Smckusick * in this block. it is either 673191Smckusick * a redeclared symbol (error) 683191Smckusick * a forward declaration, 693191Smckusick * or an external declaration. 707589Speter * check that forwards are of the right kind: 717589Speter * if this fails, we are trying to redefine it 727589Speter * and enter() will complain. 733191Smckusick */ 747589Speter if ( ( ( p->nl_flags & NFORWD ) != 0 ) 7514731Sthien && ( ( p->class == FUNC && r->tag == T_FDEC ) 7614731Sthien || ( p->class == PROC && r->tag == T_PDEC ) ) ) { 773191Smckusick /* 783191Smckusick * Grammar doesnt forbid 793191Smckusick * types on a resolution 803191Smckusick * of a forward function 813191Smckusick * declaration. 823191Smckusick */ 8314731Sthien if (p->class == FUNC && r->p_dec.type) 843191Smckusick error("Function type should be given only in forward declaration"); 853191Smckusick /* 863191Smckusick * get another counter for the actual 873191Smckusick */ 883191Smckusick if ( monflg ) { 893191Smckusick bodycnts[ cbn ] = getcnt(); 903191Smckusick } 913191Smckusick # ifdef PC 923191Smckusick enclosing[ cbn ] = p -> symbol; 933191Smckusick # endif PC 943191Smckusick # ifdef PTREE 953191Smckusick /* 963191Smckusick * mark this proc/func as forward 973191Smckusick * in the pTree. 983191Smckusick */ 993191Smckusick pDEF( p -> inTree ).PorFForward = TRUE; 1003191Smckusick # endif PTREE 1013191Smckusick return (p); 1023191Smckusick } 1033191Smckusick } 1043191Smckusick 1053191Smckusick /* if a routine segment is being compiled, 1063191Smckusick * do level one processing. 1073191Smckusick */ 1083191Smckusick 10914731Sthien if ((r->tag != T_PROG) && (!progseen)) 1103191Smckusick level1(); 1113191Smckusick 1123191Smckusick 1133191Smckusick /* 1143191Smckusick * Declare the prog/proc/func 1153191Smckusick */ 11614731Sthien switch (r->tag) { 1173191Smckusick case T_PROG: 1183191Smckusick progseen = TRUE; 1193191Smckusick if (opt('z')) 1203191Smckusick monflg = TRUE; 12114731Sthien program = p = defnl(r->p_dec.id_ptr, PROG, NLNIL, 0); 12214731Sthien p->value[3] = r->p_dec.line_no; 1233191Smckusick break; 1243191Smckusick case T_PDEC: 12514731Sthien if (r->p_dec.type != TR_NIL) 1263191Smckusick error("Procedures do not have types, only functions do"); 12714731Sthien p = enter(defnl(r->p_dec.id_ptr, PROC, NLNIL, 0)); 1283191Smckusick p->nl_flags |= NMOD; 1293191Smckusick # ifdef PC 13014731Sthien enclosing[ cbn ] = r->p_dec.id_ptr; 1313838Speter p -> extra_flags |= NGLOBAL; 1323191Smckusick # endif PC 1333191Smckusick break; 1343191Smckusick case T_FDEC: 13514731Sthien { 13614731Sthien register struct tnode *il; 13714731Sthien il = r->p_dec.type; 13818136Smckusick if (il == TR_NIL) { 13918136Smckusick temp = NLNIL; 1403191Smckusick error("Function type must be specified"); 14118136Smckusick } else if (il->tag != T_TYID) { 14214731Sthien temp = NLNIL; 1433191Smckusick error("Function type can be specified only by using a type identifier"); 1443191Smckusick } else 14514731Sthien temp = gtype(il); 14614731Sthien } 14718136Smckusick p = enter(defnl(r->p_dec.id_ptr, FUNC, temp, NIL)); 1483191Smckusick p->nl_flags |= NMOD; 1493191Smckusick /* 1503191Smckusick * An arbitrary restriction 1513191Smckusick */ 1523191Smckusick switch (o = classify(p->type)) { 1533191Smckusick case TFILE: 1543191Smckusick case TARY: 1553191Smckusick case TREC: 1563191Smckusick case TSET: 1573191Smckusick case TSTR: 1583191Smckusick warning(); 1593191Smckusick if (opt('s')) { 1603191Smckusick standard(); 1613191Smckusick } 1623191Smckusick error("Functions should not return %ss", clnames[o]); 1633191Smckusick } 1643191Smckusick # ifdef PC 16514731Sthien enclosing[ cbn ] = r->p_dec.id_ptr; 1663838Speter p -> extra_flags |= NGLOBAL; 1673191Smckusick # endif PC 1683191Smckusick break; 1693191Smckusick default: 1703191Smckusick panic("funchdr"); 1713191Smckusick } 17214731Sthien if (r->tag != T_PROG) { 1733191Smckusick /* 1743191Smckusick * Mark this proc/func as 1753191Smckusick * being forward declared 1763191Smckusick */ 1773191Smckusick p->nl_flags |= NFORWD; 1783191Smckusick /* 1793191Smckusick * Enter the parameters 1803191Smckusick * in the next block for 1813191Smckusick * the time being 1823191Smckusick */ 1833191Smckusick if (++cbn >= DSPLYSZ) { 1843191Smckusick error("Procedure/function nesting too deep"); 1853191Smckusick pexit(ERRS); 1863191Smckusick } 1873191Smckusick /* 1883191Smckusick * For functions, the function variable 1893191Smckusick */ 1903191Smckusick if (p->class == FUNC) { 1913191Smckusick # ifdef OBJ 19214731Sthien cp = defnl(r->p_dec.id_ptr, FVAR, p->type, 0); 1933191Smckusick # endif OBJ 1943191Smckusick # ifdef PC 1953191Smckusick /* 1963191Smckusick * fvars used to be allocated and deallocated 1973191Smckusick * by the caller right before the arguments. 1983191Smckusick * the offset of the fvar was kept in 1993191Smckusick * value[NL_OFFS] of function (very wierd, 2003191Smckusick * but see asgnop). 2013191Smckusick * now, they are locals to the function 2023191Smckusick * with the offset kept in the fvar. 2033191Smckusick */ 2043191Smckusick 20514731Sthien cp = defnl(r->p_dec.id_ptr, FVAR, p->type, 20630037Smckusick (int)-roundup(roundup( 2073302Smckusic (int)(DPOFF1+lwidth(p->type)), 20830037Smckusick (long)align(p->type))), (long) A_STACK); 2093838Speter cp -> extra_flags |= NLOCAL; 2103191Smckusick # endif PC 2113191Smckusick cp->chain = p; 2123191Smckusick p->ptr[NL_FVAR] = cp; 2133191Smckusick } 2143191Smckusick /* 2153191Smckusick * Enter the parameters 2163191Smckusick * and compute total size 2173191Smckusick */ 21814731Sthien p->value[NL_OFFS] = params(p, r->p_dec.param_list); 2193302Smckusic /* 2203302Smckusic * because NL_LINENO field in the function 2213302Smckusic * namelist entry has been used (as have all 2223302Smckusic * the other fields), the line number is 2233302Smckusic * stored in the NL_LINENO field of its fvar. 2243302Smckusic */ 2253302Smckusic if (p->class == FUNC) 22614731Sthien p->ptr[NL_FVAR]->value[NL_LINENO] = r->p_dec.line_no; 2273302Smckusic else 22814731Sthien p->value[NL_LINENO] = r->p_dec.line_no; 2293191Smckusick cbn--; 2303191Smckusick } else { 2313191Smckusick /* 2323191Smckusick * The wonderful 2333191Smckusick * program statement! 2343191Smckusick */ 2353191Smckusick # ifdef OBJ 2363191Smckusick if (monflg) { 23714731Sthien (void) put(1, O_PXPBUF); 2383191Smckusick cntpatch = put(2, O_CASE4, (long)0); 2393191Smckusick nfppatch = put(2, O_CASE4, (long)0); 2403191Smckusick } 2413191Smckusick # endif OBJ 2423191Smckusick cp = p; 24314731Sthien for (rl = r->p_dec.param_list; rl; rl = rl->list_node.next) { 24414731Sthien if (rl->list_node.list == TR_NIL) 2453191Smckusick continue; 24614731Sthien dp = defnl((char *) rl->list_node.list, VAR, NLNIL, 0); 2473191Smckusick cp->chain = dp; 2483191Smckusick cp = dp; 2493191Smckusick } 2503191Smckusick } 2513191Smckusick /* 2523191Smckusick * Define a branch at 2533191Smckusick * the "entry point" of 2543191Smckusick * the prog/proc/func. 2553191Smckusick */ 25614731Sthien p->value[NL_ENTLOC] = (int) getlab(); 2573191Smckusick if (monflg) { 2583191Smckusick bodycnts[ cbn ] = getcnt(); 2593191Smckusick p->value[ NL_CNTR ] = 0; 2603191Smckusick } 2613191Smckusick # ifdef OBJ 26214731Sthien (void) put(2, O_TRA4, (long)p->value[NL_ENTLOC]); 2633191Smckusick # endif OBJ 2643191Smckusick # ifdef PTREE 2653191Smckusick { 2663191Smckusick pPointer PF = tCopy( r ); 2673191Smckusick 2683191Smckusick pSeize( PorFHeader[ nesting ] ); 26914731Sthien if ( r->tag != T_PROG ) { 2703191Smckusick pPointer *PFs; 2713191Smckusick 2723191Smckusick PFs = &( pDEF( PorFHeader[ nesting ] ).PorFPFs ); 2733191Smckusick *PFs = ListAppend( *PFs , PF ); 2743191Smckusick } else { 2753191Smckusick pDEF( PorFHeader[ nesting ] ).GlobProg = PF; 2763191Smckusick } 2773191Smckusick pRelease( PorFHeader[ nesting ] ); 2783191Smckusick } 2793191Smckusick # endif PTREE 2803191Smckusick return (p); 2813191Smckusick } 2823302Smckusic 2833302Smckusic /* 2843302Smckusic * deal with the parameter declaration for a routine. 2853302Smckusic * p is the namelist entry of the routine. 2863302Smckusic * formalist is the parse tree for the parameter declaration. 2873302Smckusic * formalist [0] T_LISTPP 2883302Smckusic * [1] pointer to a formal 2893302Smckusic * [2] pointer to next formal 2903302Smckusic * for by-value or by-reference formals, the formal is 2913302Smckusic * formal [0] T_PVAL or T_PVAR 2923302Smckusic * [1] pointer to id_list 2933302Smckusic * [2] pointer to type (error if not typeid) 2943302Smckusic * for function and procedure formals, the formal is 2953302Smckusic * formal [0] T_PFUNC or T_PPROC 2963302Smckusic * [1] pointer to id_list (error if more than one) 2973302Smckusic * [2] pointer to type (error if not typeid, or proc) 2983302Smckusic * [3] pointer to formalist for this routine. 2993302Smckusic */ 3003302Smckusic fparams(p, formal) 3013302Smckusic register struct nl *p; 30214731Sthien struct tnode *formal; /* T_PFUNC or T_PPROC */ 3033302Smckusic { 30414731Sthien (void) params(p, formal->pfunc_node.param_list); 30514731Sthien p -> value[ NL_LINENO ] = formal->pfunc_node.line_no; 3063302Smckusic p -> ptr[ NL_FCHAIN ] = p -> chain; 3073302Smckusic p -> chain = NIL; 3083302Smckusic } 3093302Smckusic 3103302Smckusic params(p, formalist) 3113302Smckusic register struct nl *p; 31214731Sthien struct tnode *formalist; /* T_LISTPP */ 3133302Smckusic { 3143302Smckusic struct nl *chainp, *savedp; 3153302Smckusic struct nl *dp; 31614731Sthien register struct tnode *formalp; /* an element of the formal list */ 31714731Sthien register struct tnode *formal; /* a formal */ 31815969Smckusick struct tnode *r, *s, *t, *typ, *idlist; 3193302Smckusic int w, o; 3203302Smckusic 3213302Smckusic /* 3223302Smckusic * Enter the parameters 3233302Smckusic * and compute total size 3243302Smckusic */ 3253302Smckusic chainp = savedp = p; 3263302Smckusic 3273302Smckusic # ifdef OBJ 3283302Smckusic o = 0; 3293302Smckusic # endif OBJ 3303302Smckusic # ifdef PC 3313302Smckusic /* 3323302Smckusic * parameters used to be allocated backwards, 3333302Smckusic * then fixed. for pc, they are allocated correctly. 3343302Smckusic * also, they are aligned. 3353302Smckusic */ 3363302Smckusic o = DPOFF2; 3373302Smckusic # endif PC 33814731Sthien for (formalp = formalist; formalp != TR_NIL; 33914731Sthien formalp = formalp->list_node.next) { 34014731Sthien formal = formalp->list_node.list; 34114731Sthien if (formal == TR_NIL) 3423302Smckusic continue; 3433302Smckusic /* 3443302Smckusic * Parametric procedures 3453302Smckusic * don't have types !?! 3463302Smckusic */ 34714731Sthien typ = formal->pfunc_node.type; 34824051Smckusick p = NLNIL; 34914731Sthien if ( typ == TR_NIL ) { 35014731Sthien if ( formal->tag != T_PPROC ) { 3513302Smckusic error("Types must be specified for arguments"); 3523302Smckusic } 3533302Smckusic } else { 35414731Sthien if ( formal->tag == T_PPROC ) { 3553302Smckusic error("Procedures cannot have types"); 3563302Smckusic } else { 35715969Smckusick p = gtype(typ); 3583302Smckusic } 3593302Smckusic } 36014731Sthien for (idlist = formal->param.id_list; idlist != TR_NIL; 36114731Sthien idlist = idlist->list_node.next) { 36214731Sthien switch (formal->tag) { 3633302Smckusic default: 3643302Smckusic panic("funchdr2"); 3653302Smckusic case T_PVAL: 36614731Sthien if (p != NLNIL) { 3673302Smckusic if (p->class == FILET) 3683302Smckusic error("Files cannot be passed by value"); 3693302Smckusic else if (p->nl_flags & NFILES) 3703302Smckusic error("Files cannot be a component of %ss passed by value", 3713302Smckusic nameof(p)); 3723302Smckusic } 3733302Smckusic # ifdef OBJ 3743302Smckusic w = lwidth(p); 37530037Smckusick o -= roundup(w, (long) A_STACK); 3763302Smckusic # ifdef DEC11 37714731Sthien dp = defnl((char *) idlist->list_node.list, 37814731Sthien VAR, p, o); 3793302Smckusic # else 38014731Sthien dp = defnl((char *) idlist->list_node.list, 38114731Sthien VAR,p, (w < 2) ? o + 1 : o); 3823302Smckusic # endif DEC11 3833302Smckusic # endif OBJ 3843302Smckusic # ifdef PC 38514731Sthien o = roundup(o, (long) A_STACK); 38610654Speter w = lwidth(p); 38710654Speter # ifndef DEC11 38810654Speter if (w <= sizeof(int)) { 38910654Speter o += sizeof(int) - w; 39010654Speter } 39110654Speter # endif not DEC11 39214731Sthien dp = defnl((char *) idlist->list_node.list,VAR, 39314731Sthien p, o); 39410654Speter o += w; 3953302Smckusic # endif PC 3963302Smckusic dp->nl_flags |= NMOD; 3973302Smckusic break; 3983302Smckusic case T_PVAR: 3993302Smckusic # ifdef OBJ 40014731Sthien dp = defnl((char *) idlist->list_node.list, REF, 40114731Sthien p, o -= sizeof ( int * ) ); 4023302Smckusic # endif OBJ 4033302Smckusic # ifdef PC 40414731Sthien dp = defnl( (char *) idlist->list_node.list, REF, 40514731Sthien p , 40614731Sthien o = roundup( o , (long)A_STACK ) ); 4073302Smckusic o += sizeof(char *); 4083302Smckusic # endif PC 4093302Smckusic break; 4103302Smckusic case T_PFUNC: 41114731Sthien if (idlist->list_node.next != TR_NIL) { 4123302Smckusic error("Each function argument must be declared separately"); 41314731Sthien idlist->list_node.next = TR_NIL; 4143302Smckusic } 4153302Smckusic # ifdef OBJ 41614731Sthien dp = defnl((char *) idlist->list_node.list,FFUNC, 41714731Sthien p, o -= sizeof ( int * ) ); 4183302Smckusic # endif OBJ 4193302Smckusic # ifdef PC 42014731Sthien dp = defnl( (char *) idlist->list_node.list , 42114731Sthien FFUNC , p , 42214731Sthien o = roundup( o , (long)A_STACK ) ); 4233302Smckusic o += sizeof(char *); 4243302Smckusic # endif PC 4253302Smckusic dp -> nl_flags |= NMOD; 4263302Smckusic fparams(dp, formal); 4273302Smckusic break; 4283302Smckusic case T_PPROC: 42914731Sthien if (idlist->list_node.next != TR_NIL) { 4303302Smckusic error("Each procedure argument must be declared separately"); 43114731Sthien idlist->list_node.next = TR_NIL; 4323302Smckusic } 4333302Smckusic # ifdef OBJ 43414731Sthien dp = defnl((char *) idlist->list_node.list, 43514731Sthien FPROC, p, o -= sizeof ( int * ) ); 4363302Smckusic # endif OBJ 4373302Smckusic # ifdef PC 43814731Sthien dp = defnl( (char *) idlist->list_node.list , 43914731Sthien FPROC , p, 44014731Sthien o = roundup( o , (long)A_STACK ) ); 4413302Smckusic o += sizeof(char *); 4423302Smckusic # endif PC 4433302Smckusic dp -> nl_flags |= NMOD; 4443302Smckusic fparams(dp, formal); 4453302Smckusic break; 4463302Smckusic } 44714731Sthien if (dp != NLNIL) { 4483838Speter # ifdef PC 4493838Speter dp -> extra_flags |= NPARAM; 4503838Speter # endif PC 4513302Smckusic chainp->chain = dp; 4523302Smckusic chainp = dp; 4533302Smckusic } 4543302Smckusic } 45524051Smckusick if (typ != TR_NIL && typ->tag == T_TYCARY) { 45615969Smckusick # ifdef OBJ 45730037Smckusick w = -roundup(lwidth(p->chain), (long) A_STACK); 45815969Smckusick # ifndef DEC11 45915969Smckusick w = (w > -2)? w + 1 : w; 46015969Smckusick # endif 46115969Smckusick # endif OBJ 46215969Smckusick # ifdef PC 46315969Smckusick w = lwidth(p->chain); 46415969Smckusick o = roundup(o, (long)A_STACK); 46515969Smckusick # endif PC 46615969Smckusick /* 46715969Smckusick * Allocate space for upper and 46815969Smckusick * lower bounds and width. 46915969Smckusick */ 47015969Smckusick for (s=typ; s->tag == T_TYCARY; s = s->ary_ty.type) { 47115969Smckusick for (r=s->ary_ty.type_list; r != TR_NIL; 47215969Smckusick r = r->list_node.next) { 47315969Smckusick t = r->list_node.list; 47415969Smckusick p = p->chain; 47515969Smckusick # ifdef OBJ 47615969Smckusick o += w; 47715969Smckusick # endif OBJ 47815969Smckusick chainp->chain = defnl(t->crang_ty.lwb_var, 47915969Smckusick VAR, p, o); 48015969Smckusick chainp = chainp->chain; 48115969Smckusick chainp->nl_flags |= (NMOD | NUSED); 48215969Smckusick p->nptr[0] = chainp; 48315969Smckusick o += w; 48415969Smckusick chainp->chain = defnl(t->crang_ty.upb_var, 48515969Smckusick VAR, p, o); 48615969Smckusick chainp = chainp->chain; 48715969Smckusick chainp->nl_flags |= (NMOD | NUSED); 48815969Smckusick p->nptr[1] = chainp; 48915969Smckusick o += w; 49015969Smckusick chainp->chain = defnl(0, VAR, p, o); 49115969Smckusick chainp = chainp->chain; 49215969Smckusick chainp->nl_flags |= (NMOD | NUSED); 49315969Smckusick p->nptr[2] = chainp; 49415969Smckusick # ifdef PC 49515969Smckusick o += w; 49615969Smckusick # endif PC 49715969Smckusick } 49815969Smckusick } 49915969Smckusick } 5003302Smckusic } 5013302Smckusic p = savedp; 5023302Smckusic # ifdef OBJ 5033302Smckusic /* 5043302Smckusic * Correct the naivete (naivety) 5053302Smckusic * of our above code to 5063302Smckusic * calculate offsets 5073302Smckusic */ 50814731Sthien for (dp = p->chain; dp != NLNIL; dp = dp->chain) 5093302Smckusic dp->value[NL_OFFS] += -o + DPOFF2; 5103302Smckusic return (-o + DPOFF2); 5113302Smckusic # endif OBJ 5123302Smckusic # ifdef PC 5133302Smckusic return roundup( o , (long)A_STACK ); 5143302Smckusic # endif PC 5153302Smckusic } 516