1*22165Sdist /* 2*22165Sdist * Copyright (c) 1980 Regents of the University of California. 3*22165Sdist * All rights reserved. The Berkeley software License Agreement 4*22165Sdist * specifies the terms and conditions for redistribution. 5*22165Sdist */ 63191Smckusick 714731Sthien #ifndef lint 8*22165Sdist static char sccsid[] = "@(#)fhdr.c 5.1 (Berkeley) 06/05/85"; 9*22165Sdist #endif not lint 103191Smckusick 113191Smckusick #include "whoami.h" 123191Smckusick #include "0.h" 133191Smckusick #include "tree.h" 143191Smckusick #include "opcode.h" 153191Smckusick #include "objfmt.h" 163191Smckusick #include "align.h" 1714731Sthien #include "tree_ty.h" 183191Smckusick 193191Smckusick /* 203191Smckusick * this array keeps the pxp counters associated with 213191Smckusick * functions and procedures, so that they can be output 223191Smckusick * when their bodies are encountered 233191Smckusick */ 243191Smckusick int bodycnts[ DSPLYSZ ]; 253191Smckusick 263191Smckusick #ifdef PC 273191Smckusick # include "pc.h" 283191Smckusick #endif PC 293191Smckusick 303191Smckusick #ifdef OBJ 313191Smckusick int cntpatch; 323191Smckusick int nfppatch; 333191Smckusick #endif OBJ 343191Smckusick 353191Smckusick /* 363191Smckusick * Funchdr inserts 373191Smckusick * declaration of a the 383191Smckusick * prog/proc/func into the 393191Smckusick * namelist. It also handles 403191Smckusick * the arguments and puts out 413191Smckusick * a transfer which defines 423191Smckusick * the entry point of a procedure. 433191Smckusick */ 443191Smckusick 453191Smckusick struct nl * 463191Smckusick funchdr(r) 4714731Sthien struct tnode *r; 483191Smckusick { 493191Smckusick register struct nl *p; 5014731Sthien register struct tnode *rl; 5114731Sthien struct nl *cp, *dp, *temp; 5214731Sthien int o; 533191Smckusick 5414731Sthien if (inpflist(r->p_dec.id_ptr)) { 553191Smckusick opush('l'); 563191Smckusick yyretrieve(); /* kludge */ 573191Smckusick } 583191Smckusick pfcnt++; 593191Smckusick parts[ cbn ] |= RPRT; 6014731Sthien line = r->p_dec.line_no; 6114731Sthien if (r->p_dec.param_list == TR_NIL && 6214731Sthien (p=lookup1(r->p_dec.id_ptr)) != NIL && bn == cbn) { 633191Smckusick /* 643191Smckusick * Symbol already defined 653191Smckusick * in this block. it is either 663191Smckusick * a redeclared symbol (error) 673191Smckusick * a forward declaration, 683191Smckusick * or an external declaration. 697589Speter * check that forwards are of the right kind: 707589Speter * if this fails, we are trying to redefine it 717589Speter * and enter() will complain. 723191Smckusick */ 737589Speter if ( ( ( p->nl_flags & NFORWD ) != 0 ) 7414731Sthien && ( ( p->class == FUNC && r->tag == T_FDEC ) 7514731Sthien || ( p->class == PROC && r->tag == T_PDEC ) ) ) { 763191Smckusick /* 773191Smckusick * Grammar doesnt forbid 783191Smckusick * types on a resolution 793191Smckusick * of a forward function 803191Smckusick * declaration. 813191Smckusick */ 8214731Sthien if (p->class == FUNC && r->p_dec.type) 833191Smckusick error("Function type should be given only in forward declaration"); 843191Smckusick /* 853191Smckusick * get another counter for the actual 863191Smckusick */ 873191Smckusick if ( monflg ) { 883191Smckusick bodycnts[ cbn ] = getcnt(); 893191Smckusick } 903191Smckusick # ifdef PC 913191Smckusick enclosing[ cbn ] = p -> symbol; 923191Smckusick # endif PC 933191Smckusick # ifdef PTREE 943191Smckusick /* 953191Smckusick * mark this proc/func as forward 963191Smckusick * in the pTree. 973191Smckusick */ 983191Smckusick pDEF( p -> inTree ).PorFForward = TRUE; 993191Smckusick # endif PTREE 1003191Smckusick return (p); 1013191Smckusick } 1023191Smckusick } 1033191Smckusick 1043191Smckusick /* if a routine segment is being compiled, 1053191Smckusick * do level one processing. 1063191Smckusick */ 1073191Smckusick 10814731Sthien if ((r->tag != T_PROG) && (!progseen)) 1093191Smckusick level1(); 1103191Smckusick 1113191Smckusick 1123191Smckusick /* 1133191Smckusick * Declare the prog/proc/func 1143191Smckusick */ 11514731Sthien switch (r->tag) { 1163191Smckusick case T_PROG: 1173191Smckusick progseen = TRUE; 1183191Smckusick if (opt('z')) 1193191Smckusick monflg = TRUE; 12014731Sthien program = p = defnl(r->p_dec.id_ptr, PROG, NLNIL, 0); 12114731Sthien p->value[3] = r->p_dec.line_no; 1223191Smckusick break; 1233191Smckusick case T_PDEC: 12414731Sthien if (r->p_dec.type != TR_NIL) 1253191Smckusick error("Procedures do not have types, only functions do"); 12614731Sthien p = enter(defnl(r->p_dec.id_ptr, PROC, NLNIL, 0)); 1273191Smckusick p->nl_flags |= NMOD; 1283191Smckusick # ifdef PC 12914731Sthien enclosing[ cbn ] = r->p_dec.id_ptr; 1303838Speter p -> extra_flags |= NGLOBAL; 1313191Smckusick # endif PC 1323191Smckusick break; 1333191Smckusick case T_FDEC: 13414731Sthien { 13514731Sthien register struct tnode *il; 13614731Sthien il = r->p_dec.type; 13718136Smckusick if (il == TR_NIL) { 13818136Smckusick temp = NLNIL; 1393191Smckusick error("Function type must be specified"); 14018136Smckusick } else if (il->tag != T_TYID) { 14114731Sthien temp = NLNIL; 1423191Smckusick error("Function type can be specified only by using a type identifier"); 1433191Smckusick } else 14414731Sthien temp = gtype(il); 14514731Sthien } 14618136Smckusick p = enter(defnl(r->p_dec.id_ptr, FUNC, temp, NIL)); 1473191Smckusick p->nl_flags |= NMOD; 1483191Smckusick /* 1493191Smckusick * An arbitrary restriction 1503191Smckusick */ 1513191Smckusick switch (o = classify(p->type)) { 1523191Smckusick case TFILE: 1533191Smckusick case TARY: 1543191Smckusick case TREC: 1553191Smckusick case TSET: 1563191Smckusick case TSTR: 1573191Smckusick warning(); 1583191Smckusick if (opt('s')) { 1593191Smckusick standard(); 1603191Smckusick } 1613191Smckusick error("Functions should not return %ss", clnames[o]); 1623191Smckusick } 1633191Smckusick # ifdef PC 16414731Sthien enclosing[ cbn ] = r->p_dec.id_ptr; 1653838Speter p -> extra_flags |= NGLOBAL; 1663191Smckusick # endif PC 1673191Smckusick break; 1683191Smckusick default: 1693191Smckusick panic("funchdr"); 1703191Smckusick } 17114731Sthien if (r->tag != T_PROG) { 1723191Smckusick /* 1733191Smckusick * Mark this proc/func as 1743191Smckusick * being forward declared 1753191Smckusick */ 1763191Smckusick p->nl_flags |= NFORWD; 1773191Smckusick /* 1783191Smckusick * Enter the parameters 1793191Smckusick * in the next block for 1803191Smckusick * the time being 1813191Smckusick */ 1823191Smckusick if (++cbn >= DSPLYSZ) { 1833191Smckusick error("Procedure/function nesting too deep"); 1843191Smckusick pexit(ERRS); 1853191Smckusick } 1863191Smckusick /* 1873191Smckusick * For functions, the function variable 1883191Smckusick */ 1893191Smckusick if (p->class == FUNC) { 1903191Smckusick # ifdef OBJ 19114731Sthien cp = defnl(r->p_dec.id_ptr, FVAR, p->type, 0); 1923191Smckusick # endif OBJ 1933191Smckusick # ifdef PC 1943191Smckusick /* 1953191Smckusick * fvars used to be allocated and deallocated 1963191Smckusick * by the caller right before the arguments. 1973191Smckusick * the offset of the fvar was kept in 1983191Smckusick * value[NL_OFFS] of function (very wierd, 1993191Smckusick * but see asgnop). 2003191Smckusick * now, they are locals to the function 2013191Smckusick * with the offset kept in the fvar. 2023191Smckusick */ 2033191Smckusick 20414731Sthien cp = defnl(r->p_dec.id_ptr, FVAR, p->type, 2053302Smckusic (int)-leven(roundup( 2063302Smckusic (int)(DPOFF1+lwidth(p->type)), 2073302Smckusic (long)align(p->type)))); 2083838Speter cp -> extra_flags |= NLOCAL; 2093191Smckusick # endif PC 2103191Smckusick cp->chain = p; 2113191Smckusick p->ptr[NL_FVAR] = cp; 2123191Smckusick } 2133191Smckusick /* 2143191Smckusick * Enter the parameters 2153191Smckusick * and compute total size 2163191Smckusick */ 21714731Sthien p->value[NL_OFFS] = params(p, r->p_dec.param_list); 2183302Smckusic /* 2193302Smckusic * because NL_LINENO field in the function 2203302Smckusic * namelist entry has been used (as have all 2213302Smckusic * the other fields), the line number is 2223302Smckusic * stored in the NL_LINENO field of its fvar. 2233302Smckusic */ 2243302Smckusic if (p->class == FUNC) 22514731Sthien p->ptr[NL_FVAR]->value[NL_LINENO] = r->p_dec.line_no; 2263302Smckusic else 22714731Sthien p->value[NL_LINENO] = r->p_dec.line_no; 2283191Smckusick cbn--; 2293191Smckusick } else { 2303191Smckusick /* 2313191Smckusick * The wonderful 2323191Smckusick * program statement! 2333191Smckusick */ 2343191Smckusick # ifdef OBJ 2353191Smckusick if (monflg) { 23614731Sthien (void) put(1, O_PXPBUF); 2373191Smckusick cntpatch = put(2, O_CASE4, (long)0); 2383191Smckusick nfppatch = put(2, O_CASE4, (long)0); 2393191Smckusick } 2403191Smckusick # endif OBJ 2413191Smckusick cp = p; 24214731Sthien for (rl = r->p_dec.param_list; rl; rl = rl->list_node.next) { 24314731Sthien if (rl->list_node.list == TR_NIL) 2443191Smckusick continue; 24514731Sthien dp = defnl((char *) rl->list_node.list, VAR, NLNIL, 0); 2463191Smckusick cp->chain = dp; 2473191Smckusick cp = dp; 2483191Smckusick } 2493191Smckusick } 2503191Smckusick /* 2513191Smckusick * Define a branch at 2523191Smckusick * the "entry point" of 2533191Smckusick * the prog/proc/func. 2543191Smckusick */ 25514731Sthien p->value[NL_ENTLOC] = (int) getlab(); 2563191Smckusick if (monflg) { 2573191Smckusick bodycnts[ cbn ] = getcnt(); 2583191Smckusick p->value[ NL_CNTR ] = 0; 2593191Smckusick } 2603191Smckusick # ifdef OBJ 26114731Sthien (void) put(2, O_TRA4, (long)p->value[NL_ENTLOC]); 2623191Smckusick # endif OBJ 2633191Smckusick # ifdef PTREE 2643191Smckusick { 2653191Smckusick pPointer PF = tCopy( r ); 2663191Smckusick 2673191Smckusick pSeize( PorFHeader[ nesting ] ); 26814731Sthien if ( r->tag != T_PROG ) { 2693191Smckusick pPointer *PFs; 2703191Smckusick 2713191Smckusick PFs = &( pDEF( PorFHeader[ nesting ] ).PorFPFs ); 2723191Smckusick *PFs = ListAppend( *PFs , PF ); 2733191Smckusick } else { 2743191Smckusick pDEF( PorFHeader[ nesting ] ).GlobProg = PF; 2753191Smckusick } 2763191Smckusick pRelease( PorFHeader[ nesting ] ); 2773191Smckusick } 2783191Smckusick # endif PTREE 2793191Smckusick return (p); 2803191Smckusick } 2813302Smckusic 2823302Smckusic /* 2833302Smckusic * deal with the parameter declaration for a routine. 2843302Smckusic * p is the namelist entry of the routine. 2853302Smckusic * formalist is the parse tree for the parameter declaration. 2863302Smckusic * formalist [0] T_LISTPP 2873302Smckusic * [1] pointer to a formal 2883302Smckusic * [2] pointer to next formal 2893302Smckusic * for by-value or by-reference formals, the formal is 2903302Smckusic * formal [0] T_PVAL or T_PVAR 2913302Smckusic * [1] pointer to id_list 2923302Smckusic * [2] pointer to type (error if not typeid) 2933302Smckusic * for function and procedure formals, the formal is 2943302Smckusic * formal [0] T_PFUNC or T_PPROC 2953302Smckusic * [1] pointer to id_list (error if more than one) 2963302Smckusic * [2] pointer to type (error if not typeid, or proc) 2973302Smckusic * [3] pointer to formalist for this routine. 2983302Smckusic */ 2993302Smckusic fparams(p, formal) 3003302Smckusic register struct nl *p; 30114731Sthien struct tnode *formal; /* T_PFUNC or T_PPROC */ 3023302Smckusic { 30314731Sthien (void) params(p, formal->pfunc_node.param_list); 30414731Sthien p -> value[ NL_LINENO ] = formal->pfunc_node.line_no; 3053302Smckusic p -> ptr[ NL_FCHAIN ] = p -> chain; 3063302Smckusic p -> chain = NIL; 3073302Smckusic } 3083302Smckusic 3093302Smckusic params(p, formalist) 3103302Smckusic register struct nl *p; 31114731Sthien struct tnode *formalist; /* T_LISTPP */ 3123302Smckusic { 3133302Smckusic struct nl *chainp, *savedp; 3143302Smckusic struct nl *dp; 31514731Sthien register struct tnode *formalp; /* an element of the formal list */ 31614731Sthien register struct tnode *formal; /* a formal */ 31715969Smckusick struct tnode *r, *s, *t, *typ, *idlist; 3183302Smckusic int w, o; 3193302Smckusic 3203302Smckusic /* 3213302Smckusic * Enter the parameters 3223302Smckusic * and compute total size 3233302Smckusic */ 3243302Smckusic chainp = savedp = p; 3253302Smckusic 3263302Smckusic # ifdef OBJ 3273302Smckusic o = 0; 3283302Smckusic # endif OBJ 3293302Smckusic # ifdef PC 3303302Smckusic /* 3313302Smckusic * parameters used to be allocated backwards, 3323302Smckusic * then fixed. for pc, they are allocated correctly. 3333302Smckusic * also, they are aligned. 3343302Smckusic */ 3353302Smckusic o = DPOFF2; 3363302Smckusic # endif PC 33714731Sthien for (formalp = formalist; formalp != TR_NIL; 33814731Sthien formalp = formalp->list_node.next) { 33914731Sthien p = NLNIL; 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; 34814731Sthien if ( typ == TR_NIL ) { 34914731Sthien if ( formal->tag != T_PPROC ) { 3503302Smckusic error("Types must be specified for arguments"); 35114731Sthien p = NLNIL; 3523302Smckusic } 3533302Smckusic } else { 35414731Sthien if ( formal->tag == T_PPROC ) { 3553302Smckusic error("Procedures cannot have types"); 35614731Sthien p = NLNIL; 3573302Smckusic } else { 35815969Smckusick p = gtype(typ); 3593302Smckusic } 3603302Smckusic } 36114731Sthien for (idlist = formal->param.id_list; idlist != TR_NIL; 36214731Sthien idlist = idlist->list_node.next) { 36314731Sthien switch (formal->tag) { 3643302Smckusic default: 3653302Smckusic panic("funchdr2"); 3663302Smckusic case T_PVAL: 36714731Sthien if (p != NLNIL) { 3683302Smckusic if (p->class == FILET) 3693302Smckusic error("Files cannot be passed by value"); 3703302Smckusic else if (p->nl_flags & NFILES) 3713302Smckusic error("Files cannot be a component of %ss passed by value", 3723302Smckusic nameof(p)); 3733302Smckusic } 3743302Smckusic # ifdef OBJ 3753302Smckusic w = lwidth(p); 3763302Smckusic o -= even(w); 3773302Smckusic # ifdef DEC11 37814731Sthien dp = defnl((char *) idlist->list_node.list, 37914731Sthien VAR, p, o); 3803302Smckusic # else 38114731Sthien dp = defnl((char *) idlist->list_node.list, 38214731Sthien VAR,p, (w < 2) ? o + 1 : o); 3833302Smckusic # endif DEC11 3843302Smckusic # endif OBJ 3853302Smckusic # ifdef PC 38614731Sthien o = roundup(o, (long) A_STACK); 38710654Speter w = lwidth(p); 38810654Speter # ifndef DEC11 38910654Speter if (w <= sizeof(int)) { 39010654Speter o += sizeof(int) - w; 39110654Speter } 39210654Speter # endif not DEC11 39314731Sthien dp = defnl((char *) idlist->list_node.list,VAR, 39414731Sthien p, o); 39510654Speter o += w; 3963302Smckusic # endif PC 3973302Smckusic dp->nl_flags |= NMOD; 3983302Smckusic break; 3993302Smckusic case T_PVAR: 4003302Smckusic # ifdef OBJ 40114731Sthien dp = defnl((char *) idlist->list_node.list, REF, 40214731Sthien p, o -= sizeof ( int * ) ); 4033302Smckusic # endif OBJ 4043302Smckusic # ifdef PC 40514731Sthien dp = defnl( (char *) idlist->list_node.list, REF, 40614731Sthien p , 40714731Sthien o = roundup( o , (long)A_STACK ) ); 4083302Smckusic o += sizeof(char *); 4093302Smckusic # endif PC 4103302Smckusic break; 4113302Smckusic case T_PFUNC: 41214731Sthien if (idlist->list_node.next != TR_NIL) { 4133302Smckusic error("Each function argument must be declared separately"); 41414731Sthien idlist->list_node.next = TR_NIL; 4153302Smckusic } 4163302Smckusic # ifdef OBJ 41714731Sthien dp = defnl((char *) idlist->list_node.list,FFUNC, 41814731Sthien p, o -= sizeof ( int * ) ); 4193302Smckusic # endif OBJ 4203302Smckusic # ifdef PC 42114731Sthien dp = defnl( (char *) idlist->list_node.list , 42214731Sthien FFUNC , p , 42314731Sthien o = roundup( o , (long)A_STACK ) ); 4243302Smckusic o += sizeof(char *); 4253302Smckusic # endif PC 4263302Smckusic dp -> nl_flags |= NMOD; 4273302Smckusic fparams(dp, formal); 4283302Smckusic break; 4293302Smckusic case T_PPROC: 43014731Sthien if (idlist->list_node.next != TR_NIL) { 4313302Smckusic error("Each procedure argument must be declared separately"); 43214731Sthien idlist->list_node.next = TR_NIL; 4333302Smckusic } 4343302Smckusic # ifdef OBJ 43514731Sthien dp = defnl((char *) idlist->list_node.list, 43614731Sthien FPROC, p, o -= sizeof ( int * ) ); 4373302Smckusic # endif OBJ 4383302Smckusic # ifdef PC 43914731Sthien dp = defnl( (char *) idlist->list_node.list , 44014731Sthien FPROC , p, 44114731Sthien o = roundup( o , (long)A_STACK ) ); 4423302Smckusic o += sizeof(char *); 4433302Smckusic # endif PC 4443302Smckusic dp -> nl_flags |= NMOD; 4453302Smckusic fparams(dp, formal); 4463302Smckusic break; 4473302Smckusic } 44814731Sthien if (dp != NLNIL) { 4493838Speter # ifdef PC 4503838Speter dp -> extra_flags |= NPARAM; 4513838Speter # endif PC 4523302Smckusic chainp->chain = dp; 4533302Smckusic chainp = dp; 4543302Smckusic } 4553302Smckusic } 45615969Smckusick if (typ->tag == T_TYCARY) { 45715969Smckusick # ifdef OBJ 45815969Smckusick w = -even(lwidth(p->chain)); 45915969Smckusick # ifndef DEC11 46015969Smckusick w = (w > -2)? w + 1 : w; 46115969Smckusick # endif 46215969Smckusick # endif OBJ 46315969Smckusick # ifdef PC 46415969Smckusick w = lwidth(p->chain); 46515969Smckusick o = roundup(o, (long)A_STACK); 46615969Smckusick # endif PC 46715969Smckusick /* 46815969Smckusick * Allocate space for upper and 46915969Smckusick * lower bounds and width. 47015969Smckusick */ 47115969Smckusick for (s=typ; s->tag == T_TYCARY; s = s->ary_ty.type) { 47215969Smckusick for (r=s->ary_ty.type_list; r != TR_NIL; 47315969Smckusick r = r->list_node.next) { 47415969Smckusick t = r->list_node.list; 47515969Smckusick p = p->chain; 47615969Smckusick # ifdef OBJ 47715969Smckusick o += w; 47815969Smckusick # endif OBJ 47915969Smckusick chainp->chain = defnl(t->crang_ty.lwb_var, 48015969Smckusick VAR, p, o); 48115969Smckusick chainp = chainp->chain; 48215969Smckusick chainp->nl_flags |= (NMOD | NUSED); 48315969Smckusick p->nptr[0] = chainp; 48415969Smckusick o += w; 48515969Smckusick chainp->chain = defnl(t->crang_ty.upb_var, 48615969Smckusick VAR, p, o); 48715969Smckusick chainp = chainp->chain; 48815969Smckusick chainp->nl_flags |= (NMOD | NUSED); 48915969Smckusick p->nptr[1] = chainp; 49015969Smckusick o += w; 49115969Smckusick chainp->chain = defnl(0, VAR, p, o); 49215969Smckusick chainp = chainp->chain; 49315969Smckusick chainp->nl_flags |= (NMOD | NUSED); 49415969Smckusick p->nptr[2] = chainp; 49515969Smckusick # ifdef PC 49615969Smckusick o += w; 49715969Smckusick # endif PC 49815969Smckusick } 49915969Smckusick } 50015969Smckusick } 5013302Smckusic } 5023302Smckusic p = savedp; 5033302Smckusic # ifdef OBJ 5043302Smckusic /* 5053302Smckusic * Correct the naivete (naivety) 5063302Smckusic * of our above code to 5073302Smckusic * calculate offsets 5083302Smckusic */ 50914731Sthien for (dp = p->chain; dp != NLNIL; dp = dp->chain) 5103302Smckusic dp->value[NL_OFFS] += -o + DPOFF2; 5113302Smckusic return (-o + DPOFF2); 5123302Smckusic # endif OBJ 5133302Smckusic # ifdef PC 5143302Smckusic return roundup( o , (long)A_STACK ); 5153302Smckusic # endif PC 5163302Smckusic } 517