122165Sdist /* 222165Sdist * Copyright (c) 1980 Regents of the University of California. 322165Sdist * All rights reserved. The Berkeley software License Agreement 422165Sdist * specifies the terms and conditions for redistribution. 522165Sdist */ 63191Smckusick 714731Sthien #ifndef lint 8*30037Smckusick static char sccsid[] = "@(#)fhdr.c 5.3 (Berkeley) 11/12/86"; 922165Sdist #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, 205*30037Smckusick (int)-roundup(roundup( 2063302Smckusic (int)(DPOFF1+lwidth(p->type)), 207*30037Smckusick (long)align(p->type))), (long) A_STACK); 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 formal = formalp->list_node.list; 34014731Sthien if (formal == TR_NIL) 3413302Smckusic continue; 3423302Smckusic /* 3433302Smckusic * Parametric procedures 3443302Smckusic * don't have types !?! 3453302Smckusic */ 34614731Sthien typ = formal->pfunc_node.type; 34724051Smckusick p = NLNIL; 34814731Sthien if ( typ == TR_NIL ) { 34914731Sthien if ( formal->tag != T_PPROC ) { 3503302Smckusic error("Types must be specified for arguments"); 3513302Smckusic } 3523302Smckusic } else { 35314731Sthien if ( formal->tag == T_PPROC ) { 3543302Smckusic error("Procedures cannot have types"); 3553302Smckusic } else { 35615969Smckusick p = gtype(typ); 3573302Smckusic } 3583302Smckusic } 35914731Sthien for (idlist = formal->param.id_list; idlist != TR_NIL; 36014731Sthien idlist = idlist->list_node.next) { 36114731Sthien switch (formal->tag) { 3623302Smckusic default: 3633302Smckusic panic("funchdr2"); 3643302Smckusic case T_PVAL: 36514731Sthien if (p != NLNIL) { 3663302Smckusic if (p->class == FILET) 3673302Smckusic error("Files cannot be passed by value"); 3683302Smckusic else if (p->nl_flags & NFILES) 3693302Smckusic error("Files cannot be a component of %ss passed by value", 3703302Smckusic nameof(p)); 3713302Smckusic } 3723302Smckusic # ifdef OBJ 3733302Smckusic w = lwidth(p); 374*30037Smckusick o -= roundup(w, (long) A_STACK); 3753302Smckusic # ifdef DEC11 37614731Sthien dp = defnl((char *) idlist->list_node.list, 37714731Sthien VAR, p, o); 3783302Smckusic # else 37914731Sthien dp = defnl((char *) idlist->list_node.list, 38014731Sthien VAR,p, (w < 2) ? o + 1 : o); 3813302Smckusic # endif DEC11 3823302Smckusic # endif OBJ 3833302Smckusic # ifdef PC 38414731Sthien o = roundup(o, (long) A_STACK); 38510654Speter w = lwidth(p); 38610654Speter # ifndef DEC11 38710654Speter if (w <= sizeof(int)) { 38810654Speter o += sizeof(int) - w; 38910654Speter } 39010654Speter # endif not DEC11 39114731Sthien dp = defnl((char *) idlist->list_node.list,VAR, 39214731Sthien p, o); 39310654Speter o += w; 3943302Smckusic # endif PC 3953302Smckusic dp->nl_flags |= NMOD; 3963302Smckusic break; 3973302Smckusic case T_PVAR: 3983302Smckusic # ifdef OBJ 39914731Sthien dp = defnl((char *) idlist->list_node.list, REF, 40014731Sthien p, o -= sizeof ( int * ) ); 4013302Smckusic # endif OBJ 4023302Smckusic # ifdef PC 40314731Sthien dp = defnl( (char *) idlist->list_node.list, REF, 40414731Sthien p , 40514731Sthien o = roundup( o , (long)A_STACK ) ); 4063302Smckusic o += sizeof(char *); 4073302Smckusic # endif PC 4083302Smckusic break; 4093302Smckusic case T_PFUNC: 41014731Sthien if (idlist->list_node.next != TR_NIL) { 4113302Smckusic error("Each function argument must be declared separately"); 41214731Sthien idlist->list_node.next = TR_NIL; 4133302Smckusic } 4143302Smckusic # ifdef OBJ 41514731Sthien dp = defnl((char *) idlist->list_node.list,FFUNC, 41614731Sthien p, o -= sizeof ( int * ) ); 4173302Smckusic # endif OBJ 4183302Smckusic # ifdef PC 41914731Sthien dp = defnl( (char *) idlist->list_node.list , 42014731Sthien FFUNC , p , 42114731Sthien o = roundup( o , (long)A_STACK ) ); 4223302Smckusic o += sizeof(char *); 4233302Smckusic # endif PC 4243302Smckusic dp -> nl_flags |= NMOD; 4253302Smckusic fparams(dp, formal); 4263302Smckusic break; 4273302Smckusic case T_PPROC: 42814731Sthien if (idlist->list_node.next != TR_NIL) { 4293302Smckusic error("Each procedure argument must be declared separately"); 43014731Sthien idlist->list_node.next = TR_NIL; 4313302Smckusic } 4323302Smckusic # ifdef OBJ 43314731Sthien dp = defnl((char *) idlist->list_node.list, 43414731Sthien FPROC, p, o -= sizeof ( int * ) ); 4353302Smckusic # endif OBJ 4363302Smckusic # ifdef PC 43714731Sthien dp = defnl( (char *) idlist->list_node.list , 43814731Sthien FPROC , p, 43914731Sthien o = roundup( o , (long)A_STACK ) ); 4403302Smckusic o += sizeof(char *); 4413302Smckusic # endif PC 4423302Smckusic dp -> nl_flags |= NMOD; 4433302Smckusic fparams(dp, formal); 4443302Smckusic break; 4453302Smckusic } 44614731Sthien if (dp != NLNIL) { 4473838Speter # ifdef PC 4483838Speter dp -> extra_flags |= NPARAM; 4493838Speter # endif PC 4503302Smckusic chainp->chain = dp; 4513302Smckusic chainp = dp; 4523302Smckusic } 4533302Smckusic } 45424051Smckusick if (typ != TR_NIL && typ->tag == T_TYCARY) { 45515969Smckusick # ifdef OBJ 456*30037Smckusick w = -roundup(lwidth(p->chain), (long) A_STACK); 45715969Smckusick # ifndef DEC11 45815969Smckusick w = (w > -2)? w + 1 : w; 45915969Smckusick # endif 46015969Smckusick # endif OBJ 46115969Smckusick # ifdef PC 46215969Smckusick w = lwidth(p->chain); 46315969Smckusick o = roundup(o, (long)A_STACK); 46415969Smckusick # endif PC 46515969Smckusick /* 46615969Smckusick * Allocate space for upper and 46715969Smckusick * lower bounds and width. 46815969Smckusick */ 46915969Smckusick for (s=typ; s->tag == T_TYCARY; s = s->ary_ty.type) { 47015969Smckusick for (r=s->ary_ty.type_list; r != TR_NIL; 47115969Smckusick r = r->list_node.next) { 47215969Smckusick t = r->list_node.list; 47315969Smckusick p = p->chain; 47415969Smckusick # ifdef OBJ 47515969Smckusick o += w; 47615969Smckusick # endif OBJ 47715969Smckusick chainp->chain = defnl(t->crang_ty.lwb_var, 47815969Smckusick VAR, p, o); 47915969Smckusick chainp = chainp->chain; 48015969Smckusick chainp->nl_flags |= (NMOD | NUSED); 48115969Smckusick p->nptr[0] = chainp; 48215969Smckusick o += w; 48315969Smckusick chainp->chain = defnl(t->crang_ty.upb_var, 48415969Smckusick VAR, p, o); 48515969Smckusick chainp = chainp->chain; 48615969Smckusick chainp->nl_flags |= (NMOD | NUSED); 48715969Smckusick p->nptr[1] = chainp; 48815969Smckusick o += w; 48915969Smckusick chainp->chain = defnl(0, VAR, p, o); 49015969Smckusick chainp = chainp->chain; 49115969Smckusick chainp->nl_flags |= (NMOD | NUSED); 49215969Smckusick p->nptr[2] = chainp; 49315969Smckusick # ifdef PC 49415969Smckusick o += w; 49515969Smckusick # endif PC 49615969Smckusick } 49715969Smckusick } 49815969Smckusick } 4993302Smckusic } 5003302Smckusic p = savedp; 5013302Smckusic # ifdef OBJ 5023302Smckusic /* 5033302Smckusic * Correct the naivete (naivety) 5043302Smckusic * of our above code to 5053302Smckusic * calculate offsets 5063302Smckusic */ 50714731Sthien for (dp = p->chain; dp != NLNIL; dp = dp->chain) 5083302Smckusic dp->value[NL_OFFS] += -o + DPOFF2; 5093302Smckusic return (-o + DPOFF2); 5103302Smckusic # endif OBJ 5113302Smckusic # ifdef PC 5123302Smckusic return roundup( o , (long)A_STACK ); 5133302Smckusic # endif PC 5143302Smckusic } 515