13191Smckusick /* Copyright (c) 1979 Regents of the University of California */ 23191Smckusick 3*14731Sthien #ifndef lint 4*14731Sthien static char sccsid[] = "@(#)fhdr.c 1.7 08/19/83"; 5*14731Sthien #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" 13*14731Sthien #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) 44*14731Sthien struct tnode *r; 453191Smckusick { 463191Smckusick register struct nl *p; 47*14731Sthien register struct tnode *rl; 48*14731Sthien struct nl *cp, *dp, *temp; 49*14731Sthien int o; 503191Smckusick 51*14731Sthien if (inpflist(r->p_dec.id_ptr)) { 523191Smckusick opush('l'); 533191Smckusick yyretrieve(); /* kludge */ 543191Smckusick } 553191Smckusick pfcnt++; 563191Smckusick parts[ cbn ] |= RPRT; 57*14731Sthien line = r->p_dec.line_no; 58*14731Sthien if (r->p_dec.param_list == TR_NIL && 59*14731Sthien (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 ) 71*14731Sthien && ( ( p->class == FUNC && r->tag == T_FDEC ) 72*14731Sthien || ( 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 */ 79*14731Sthien 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 105*14731Sthien if ((r->tag != T_PROG) && (!progseen)) 1063191Smckusick level1(); 1073191Smckusick 1083191Smckusick 1093191Smckusick /* 1103191Smckusick * Declare the prog/proc/func 1113191Smckusick */ 112*14731Sthien switch (r->tag) { 1133191Smckusick case T_PROG: 1143191Smckusick progseen = TRUE; 1153191Smckusick if (opt('z')) 1163191Smckusick monflg = TRUE; 117*14731Sthien program = p = defnl(r->p_dec.id_ptr, PROG, NLNIL, 0); 118*14731Sthien p->value[3] = r->p_dec.line_no; 1193191Smckusick break; 1203191Smckusick case T_PDEC: 121*14731Sthien if (r->p_dec.type != TR_NIL) 1223191Smckusick error("Procedures do not have types, only functions do"); 123*14731Sthien p = enter(defnl(r->p_dec.id_ptr, PROC, NLNIL, 0)); 1243191Smckusick p->nl_flags |= NMOD; 1253191Smckusick # ifdef PC 126*14731Sthien enclosing[ cbn ] = r->p_dec.id_ptr; 1273838Speter p -> extra_flags |= NGLOBAL; 1283191Smckusick # endif PC 1293191Smckusick break; 1303191Smckusick case T_FDEC: 131*14731Sthien { 132*14731Sthien register struct tnode *il; 133*14731Sthien il = r->p_dec.type; 134*14731Sthien if (il == TR_NIL) 1353191Smckusick error("Function type must be specified"); 136*14731Sthien else if (il->tag != T_TYID) { 137*14731Sthien temp = NLNIL; 1383191Smckusick error("Function type can be specified only by using a type identifier"); 1393191Smckusick } else 140*14731Sthien temp = gtype(il); 141*14731Sthien } 142*14731Sthien { 143*14731Sthien register struct nl *il; 144*14731Sthien 145*14731Sthien il = temp; 146*14731Sthien p = enter(defnl(r->p_dec.id_ptr, FUNC, il, NIL)); 147*14731Sthien 148*14731Sthien } 149*14731Sthien 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 167*14731Sthien enclosing[ cbn ] = r->p_dec.id_ptr; 1683838Speter p -> extra_flags |= NGLOBAL; 1693191Smckusick # endif PC 1703191Smckusick break; 1713191Smckusick default: 1723191Smckusick panic("funchdr"); 1733191Smckusick } 174*14731Sthien 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 194*14731Sthien 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 207*14731Sthien 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 */ 220*14731Sthien 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) 228*14731Sthien p->ptr[NL_FVAR]->value[NL_LINENO] = r->p_dec.line_no; 2293302Smckusic else 230*14731Sthien 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) { 239*14731Sthien (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; 245*14731Sthien for (rl = r->p_dec.param_list; rl; rl = rl->list_node.next) { 246*14731Sthien if (rl->list_node.list == TR_NIL) 2473191Smckusick continue; 248*14731Sthien 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 */ 258*14731Sthien p->value[NL_ENTLOC] = (int) getlab(); 2593191Smckusick if (monflg) { 2603191Smckusick bodycnts[ cbn ] = getcnt(); 2613191Smckusick p->value[ NL_CNTR ] = 0; 2623191Smckusick } 2633191Smckusick # ifdef OBJ 264*14731Sthien (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 ] ); 271*14731Sthien 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; 304*14731Sthien struct tnode *formal; /* T_PFUNC or T_PPROC */ 3053302Smckusic { 306*14731Sthien (void) params(p, formal->pfunc_node.param_list); 307*14731Sthien 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; 314*14731Sthien struct tnode *formalist; /* T_LISTPP */ 3153302Smckusic { 3163302Smckusic struct nl *chainp, *savedp; 3173302Smckusic struct nl *dp; 318*14731Sthien register struct tnode *formalp; /* an element of the formal list */ 319*14731Sthien register struct tnode *formal; /* a formal */ 320*14731Sthien struct tnode *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 340*14731Sthien for (formalp = formalist; formalp != TR_NIL; 341*14731Sthien formalp = formalp->list_node.next) { 342*14731Sthien p = NLNIL; 343*14731Sthien formal = formalp->list_node.list; 344*14731Sthien if (formal == TR_NIL) 3453302Smckusic continue; 3463302Smckusic /* 3473302Smckusic * Parametric procedures 3483302Smckusic * don't have types !?! 3493302Smckusic */ 350*14731Sthien typ = formal->pfunc_node.type; 351*14731Sthien if ( typ == TR_NIL ) { 352*14731Sthien if ( formal->tag != T_PPROC ) { 3533302Smckusic error("Types must be specified for arguments"); 354*14731Sthien p = NLNIL; 3553302Smckusic } 3563302Smckusic } else { 357*14731Sthien if ( formal->tag == T_PPROC ) { 3583302Smckusic error("Procedures cannot have types"); 359*14731Sthien p = NLNIL; 3603302Smckusic } else { 361*14731Sthien if (typ->tag != T_TYID) { 3623302Smckusic error("Types for arguments can be specified only by using type identifiers"); 363*14731Sthien p = NLNIL; 3643302Smckusic } else { 3653302Smckusic p = gtype(typ); 3663302Smckusic } 3673302Smckusic } 3683302Smckusic } 369*14731Sthien for (idlist = formal->param.id_list; idlist != TR_NIL; 370*14731Sthien idlist = idlist->list_node.next) { 371*14731Sthien switch (formal->tag) { 3723302Smckusic default: 3733302Smckusic panic("funchdr2"); 3743302Smckusic case T_PVAL: 375*14731Sthien if (p != NLNIL) { 3763302Smckusic if (p->class == FILET) 3773302Smckusic error("Files cannot be passed by value"); 3783302Smckusic else if (p->nl_flags & NFILES) 3793302Smckusic error("Files cannot be a component of %ss passed by value", 3803302Smckusic nameof(p)); 3813302Smckusic } 3823302Smckusic # ifdef OBJ 3833302Smckusic w = lwidth(p); 3843302Smckusic o -= even(w); 3853302Smckusic # ifdef DEC11 386*14731Sthien dp = defnl((char *) idlist->list_node.list, 387*14731Sthien VAR, p, o); 3883302Smckusic # else 389*14731Sthien dp = defnl((char *) idlist->list_node.list, 390*14731Sthien VAR,p, (w < 2) ? o + 1 : o); 3913302Smckusic # endif DEC11 3923302Smckusic # endif OBJ 3933302Smckusic # ifdef PC 394*14731Sthien o = roundup(o, (long) A_STACK); 39510654Speter w = lwidth(p); 39610654Speter # ifndef DEC11 39710654Speter if (w <= sizeof(int)) { 39810654Speter o += sizeof(int) - w; 39910654Speter } 40010654Speter # endif not DEC11 401*14731Sthien dp = defnl((char *) idlist->list_node.list,VAR, 402*14731Sthien p, o); 40310654Speter o += w; 4043302Smckusic # endif PC 4053302Smckusic dp->nl_flags |= NMOD; 4063302Smckusic break; 4073302Smckusic case T_PVAR: 4083302Smckusic # ifdef OBJ 409*14731Sthien dp = defnl((char *) idlist->list_node.list, REF, 410*14731Sthien p, o -= sizeof ( int * ) ); 4113302Smckusic # endif OBJ 4123302Smckusic # ifdef PC 413*14731Sthien dp = defnl( (char *) idlist->list_node.list, REF, 414*14731Sthien p , 415*14731Sthien o = roundup( o , (long)A_STACK ) ); 4163302Smckusic o += sizeof(char *); 4173302Smckusic # endif PC 4183302Smckusic break; 4193302Smckusic case T_PFUNC: 420*14731Sthien if (idlist->list_node.next != TR_NIL) { 4213302Smckusic error("Each function argument must be declared separately"); 422*14731Sthien idlist->list_node.next = TR_NIL; 4233302Smckusic } 4243302Smckusic # ifdef OBJ 425*14731Sthien dp = defnl((char *) idlist->list_node.list,FFUNC, 426*14731Sthien p, o -= sizeof ( int * ) ); 4273302Smckusic # endif OBJ 4283302Smckusic # ifdef PC 429*14731Sthien dp = defnl( (char *) idlist->list_node.list , 430*14731Sthien FFUNC , p , 431*14731Sthien o = roundup( o , (long)A_STACK ) ); 4323302Smckusic o += sizeof(char *); 4333302Smckusic # endif PC 4343302Smckusic dp -> nl_flags |= NMOD; 4353302Smckusic fparams(dp, formal); 4363302Smckusic break; 4373302Smckusic case T_PPROC: 438*14731Sthien if (idlist->list_node.next != TR_NIL) { 4393302Smckusic error("Each procedure argument must be declared separately"); 440*14731Sthien idlist->list_node.next = TR_NIL; 4413302Smckusic } 4423302Smckusic # ifdef OBJ 443*14731Sthien dp = defnl((char *) idlist->list_node.list, 444*14731Sthien FPROC, p, o -= sizeof ( int * ) ); 4453302Smckusic # endif OBJ 4463302Smckusic # ifdef PC 447*14731Sthien dp = defnl( (char *) idlist->list_node.list , 448*14731Sthien FPROC , p, 449*14731Sthien o = roundup( o , (long)A_STACK ) ); 4503302Smckusic o += sizeof(char *); 4513302Smckusic # endif PC 4523302Smckusic dp -> nl_flags |= NMOD; 4533302Smckusic fparams(dp, formal); 4543302Smckusic break; 4553302Smckusic } 456*14731Sthien if (dp != NLNIL) { 4573838Speter # ifdef PC 4583838Speter dp -> extra_flags |= NPARAM; 4593838Speter # endif PC 4603302Smckusic chainp->chain = dp; 4613302Smckusic chainp = dp; 4623302Smckusic } 4633302Smckusic } 4643302Smckusic } 4653302Smckusic p = savedp; 4663302Smckusic # ifdef OBJ 4673302Smckusic /* 4683302Smckusic * Correct the naivete (naivety) 4693302Smckusic * of our above code to 4703302Smckusic * calculate offsets 4713302Smckusic */ 472*14731Sthien for (dp = p->chain; dp != NLNIL; dp = dp->chain) 4733302Smckusic dp->value[NL_OFFS] += -o + DPOFF2; 4743302Smckusic return (-o + DPOFF2); 4753302Smckusic # endif OBJ 4763302Smckusic # ifdef PC 4773302Smckusic return roundup( o , (long)A_STACK ); 4783302Smckusic # endif PC 4793302Smckusic } 480