13191Smckusick /* Copyright (c) 1979 Regents of the University of California */ 23191Smckusick 3*3302Smckusic static char sccsid[] = "@(#)fhdr.c 1.2 03/18/81"; 43191Smckusick 53191Smckusick #include "whoami.h" 63191Smckusick #include "0.h" 73191Smckusick #include "tree.h" 83191Smckusick #include "opcode.h" 93191Smckusick #include "objfmt.h" 103191Smckusick #include "align.h" 113191Smckusick 123191Smckusick /* 133191Smckusick * this array keeps the pxp counters associated with 143191Smckusick * functions and procedures, so that they can be output 153191Smckusick * when their bodies are encountered 163191Smckusick */ 173191Smckusick int bodycnts[ DSPLYSZ ]; 183191Smckusick 193191Smckusick #ifdef PC 203191Smckusick # include "pc.h" 213191Smckusick # include "pcops.h" 223191Smckusick #endif PC 233191Smckusick 243191Smckusick #ifdef OBJ 253191Smckusick int cntpatch; 263191Smckusick int nfppatch; 273191Smckusick #endif OBJ 283191Smckusick 293191Smckusick /* 303191Smckusick * Funchdr inserts 313191Smckusick * declaration of a the 323191Smckusick * prog/proc/func into the 333191Smckusick * namelist. It also handles 343191Smckusick * the arguments and puts out 353191Smckusick * a transfer which defines 363191Smckusick * the entry point of a procedure. 373191Smckusick */ 383191Smckusick 393191Smckusick struct nl * 403191Smckusick funchdr(r) 413191Smckusick int *r; 423191Smckusick { 433191Smckusick register struct nl *p; 443191Smckusick register *il, **rl; 45*3302Smckusic struct nl *cp, *dp; 46*3302Smckusic int s, o, *pp; 473191Smckusick 483191Smckusick if (inpflist(r[2])) { 493191Smckusick opush('l'); 503191Smckusick yyretrieve(); /* kludge */ 513191Smckusick } 523191Smckusick pfcnt++; 533191Smckusick parts[ cbn ] |= RPRT; 543191Smckusick line = r[1]; 553191Smckusick if (r[3] == NIL && (p=lookup1(r[2])) != NIL && bn == cbn) { 563191Smckusick /* 573191Smckusick * Symbol already defined 583191Smckusick * in this block. it is either 593191Smckusick * a redeclared symbol (error) 603191Smckusick * a forward declaration, 613191Smckusick * or an external declaration. 623191Smckusick */ 633191Smckusick if ((p->class == FUNC || p->class == PROC) && (p->nl_flags & NFORWD) != 0) { 643191Smckusick /* 653191Smckusick * Grammar doesnt forbid 663191Smckusick * types on a resolution 673191Smckusick * of a forward function 683191Smckusick * declaration. 693191Smckusick */ 703191Smckusick if (p->class == FUNC && r[4]) 713191Smckusick error("Function type should be given only in forward declaration"); 723191Smckusick /* 733191Smckusick * get another counter for the actual 743191Smckusick */ 753191Smckusick if ( monflg ) { 763191Smckusick bodycnts[ cbn ] = getcnt(); 773191Smckusick } 783191Smckusick # ifdef PC 793191Smckusick enclosing[ cbn ] = p -> symbol; 803191Smckusick # endif PC 813191Smckusick # ifdef PTREE 823191Smckusick /* 833191Smckusick * mark this proc/func as forward 843191Smckusick * in the pTree. 853191Smckusick */ 863191Smckusick pDEF( p -> inTree ).PorFForward = TRUE; 873191Smckusick # endif PTREE 883191Smckusick return (p); 893191Smckusick } 903191Smckusick } 913191Smckusick 923191Smckusick /* if a routine segment is being compiled, 933191Smckusick * do level one processing. 943191Smckusick */ 953191Smckusick 963191Smckusick if ((r[0] != T_PROG) && (!progseen)) 973191Smckusick level1(); 983191Smckusick 993191Smckusick 1003191Smckusick /* 1013191Smckusick * Declare the prog/proc/func 1023191Smckusick */ 1033191Smckusick switch (r[0]) { 1043191Smckusick case T_PROG: 1053191Smckusick progseen = TRUE; 1063191Smckusick if (opt('z')) 1073191Smckusick monflg = TRUE; 1083191Smckusick program = p = defnl(r[2], PROG, 0, 0); 1093191Smckusick p->value[3] = r[1]; 1103191Smckusick break; 1113191Smckusick case T_PDEC: 1123191Smckusick if (r[4] != NIL) 1133191Smckusick error("Procedures do not have types, only functions do"); 1143191Smckusick p = enter(defnl(r[2], PROC, 0, 0)); 1153191Smckusick p->nl_flags |= NMOD; 1163191Smckusick # ifdef PC 1173191Smckusick enclosing[ cbn ] = r[2]; 1183191Smckusick # endif PC 1193191Smckusick break; 1203191Smckusick case T_FDEC: 1213191Smckusick il = r[4]; 1223191Smckusick if (il == NIL) 1233191Smckusick error("Function type must be specified"); 1243191Smckusick else if (il[0] != T_TYID) { 1253191Smckusick il = NIL; 1263191Smckusick error("Function type can be specified only by using a type identifier"); 1273191Smckusick } else 1283191Smckusick il = gtype(il); 1293191Smckusick p = enter(defnl(r[2], FUNC, il, NIL)); 1303191Smckusick p->nl_flags |= NMOD; 1313191Smckusick /* 1323191Smckusick * An arbitrary restriction 1333191Smckusick */ 1343191Smckusick switch (o = classify(p->type)) { 1353191Smckusick case TFILE: 1363191Smckusick case TARY: 1373191Smckusick case TREC: 1383191Smckusick case TSET: 1393191Smckusick case TSTR: 1403191Smckusick warning(); 1413191Smckusick if (opt('s')) { 1423191Smckusick standard(); 1433191Smckusick } 1443191Smckusick error("Functions should not return %ss", clnames[o]); 1453191Smckusick } 1463191Smckusick # ifdef PC 1473191Smckusick enclosing[ cbn ] = r[2]; 1483191Smckusick # endif PC 1493191Smckusick break; 1503191Smckusick default: 1513191Smckusick panic("funchdr"); 1523191Smckusick } 1533191Smckusick if (r[0] != T_PROG) { 1543191Smckusick /* 1553191Smckusick * Mark this proc/func as 1563191Smckusick * being forward declared 1573191Smckusick */ 1583191Smckusick p->nl_flags |= NFORWD; 1593191Smckusick /* 1603191Smckusick * Enter the parameters 1613191Smckusick * in the next block for 1623191Smckusick * the time being 1633191Smckusick */ 1643191Smckusick if (++cbn >= DSPLYSZ) { 1653191Smckusick error("Procedure/function nesting too deep"); 1663191Smckusick pexit(ERRS); 1673191Smckusick } 1683191Smckusick /* 1693191Smckusick * For functions, the function variable 1703191Smckusick */ 1713191Smckusick if (p->class == FUNC) { 1723191Smckusick # ifdef OBJ 1733191Smckusick cp = defnl(r[2], FVAR, p->type, 0); 1743191Smckusick # endif OBJ 1753191Smckusick # ifdef PC 1763191Smckusick /* 1773191Smckusick * fvars used to be allocated and deallocated 1783191Smckusick * by the caller right before the arguments. 1793191Smckusick * the offset of the fvar was kept in 1803191Smckusick * value[NL_OFFS] of function (very wierd, 1813191Smckusick * but see asgnop). 1823191Smckusick * now, they are locals to the function 1833191Smckusick * with the offset kept in the fvar. 1843191Smckusick */ 1853191Smckusick 1863191Smckusick cp = defnl(r[2], FVAR, p->type, 187*3302Smckusic (int)-leven(roundup( 188*3302Smckusic (int)(DPOFF1+lwidth(p->type)), 189*3302Smckusic (long)align(p->type)))); 1903191Smckusick # endif PC 1913191Smckusick cp->chain = p; 1923191Smckusick p->ptr[NL_FVAR] = cp; 1933191Smckusick } 1943191Smckusick /* 1953191Smckusick * Enter the parameters 1963191Smckusick * and compute total size 1973191Smckusick */ 198*3302Smckusic p->value[NL_OFFS] = params(p, r[3]); 199*3302Smckusic /* 200*3302Smckusic * because NL_LINENO field in the function 201*3302Smckusic * namelist entry has been used (as have all 202*3302Smckusic * the other fields), the line number is 203*3302Smckusic * stored in the NL_LINENO field of its fvar. 204*3302Smckusic */ 205*3302Smckusic if (p->class == FUNC) 206*3302Smckusic p->ptr[NL_FVAR]->value[NL_LINENO] = r[1]; 207*3302Smckusic else 208*3302Smckusic p->value[NL_LINENO] = r[1]; 2093191Smckusick cbn--; 2103191Smckusick } else { 2113191Smckusick /* 2123191Smckusick * The wonderful 2133191Smckusick * program statement! 2143191Smckusick */ 2153191Smckusick # ifdef OBJ 2163191Smckusick if (monflg) { 2173191Smckusick put(1, O_PXPBUF); 2183191Smckusick cntpatch = put(2, O_CASE4, (long)0); 2193191Smckusick nfppatch = put(2, O_CASE4, (long)0); 2203191Smckusick } 2213191Smckusick # endif OBJ 2223191Smckusick cp = p; 2233191Smckusick for (rl = r[3]; rl; rl = rl[2]) { 2243191Smckusick if (rl[1] == NIL) 2253191Smckusick continue; 2263191Smckusick dp = defnl(rl[1], VAR, 0, 0); 2273191Smckusick cp->chain = dp; 2283191Smckusick cp = dp; 2293191Smckusick } 2303191Smckusick } 2313191Smckusick /* 2323191Smckusick * Define a branch at 2333191Smckusick * the "entry point" of 2343191Smckusick * the prog/proc/func. 2353191Smckusick */ 2363191Smckusick p->entloc = getlab(); 2373191Smckusick if (monflg) { 2383191Smckusick bodycnts[ cbn ] = getcnt(); 2393191Smckusick p->value[ NL_CNTR ] = 0; 2403191Smckusick } 2413191Smckusick # ifdef OBJ 2423191Smckusick put(2, O_TRA4, (long)p->entloc); 2433191Smckusick # endif OBJ 2443191Smckusick # ifdef PTREE 2453191Smckusick { 2463191Smckusick pPointer PF = tCopy( r ); 2473191Smckusick 2483191Smckusick pSeize( PorFHeader[ nesting ] ); 2493191Smckusick if ( r[0] != T_PROG ) { 2503191Smckusick pPointer *PFs; 2513191Smckusick 2523191Smckusick PFs = &( pDEF( PorFHeader[ nesting ] ).PorFPFs ); 2533191Smckusick *PFs = ListAppend( *PFs , PF ); 2543191Smckusick } else { 2553191Smckusick pDEF( PorFHeader[ nesting ] ).GlobProg = PF; 2563191Smckusick } 2573191Smckusick pRelease( PorFHeader[ nesting ] ); 2583191Smckusick } 2593191Smckusick # endif PTREE 2603191Smckusick return (p); 2613191Smckusick } 262*3302Smckusic 263*3302Smckusic /* 264*3302Smckusic * deal with the parameter declaration for a routine. 265*3302Smckusic * p is the namelist entry of the routine. 266*3302Smckusic * formalist is the parse tree for the parameter declaration. 267*3302Smckusic * formalist [0] T_LISTPP 268*3302Smckusic * [1] pointer to a formal 269*3302Smckusic * [2] pointer to next formal 270*3302Smckusic * for by-value or by-reference formals, the formal is 271*3302Smckusic * formal [0] T_PVAL or T_PVAR 272*3302Smckusic * [1] pointer to id_list 273*3302Smckusic * [2] pointer to type (error if not typeid) 274*3302Smckusic * for function and procedure formals, the formal is 275*3302Smckusic * formal [0] T_PFUNC or T_PPROC 276*3302Smckusic * [1] pointer to id_list (error if more than one) 277*3302Smckusic * [2] pointer to type (error if not typeid, or proc) 278*3302Smckusic * [3] pointer to formalist for this routine. 279*3302Smckusic */ 280*3302Smckusic fparams(p, formal) 281*3302Smckusic register struct nl *p; 282*3302Smckusic int *formal; 283*3302Smckusic { 284*3302Smckusic params(p, formal[3]); 285*3302Smckusic p -> value[ NL_LINENO ] = formal[4]; 286*3302Smckusic p -> ptr[ NL_FCHAIN ] = p -> chain; 287*3302Smckusic p -> chain = NIL; 288*3302Smckusic } 289*3302Smckusic 290*3302Smckusic params(p, formalist) 291*3302Smckusic register struct nl *p; 292*3302Smckusic int *formalist; 293*3302Smckusic { 294*3302Smckusic struct nl *chainp, *savedp; 295*3302Smckusic struct nl *dp; 296*3302Smckusic register int **formalp; /* an element of the formal list */ 297*3302Smckusic register int *formal; /* a formal */ 298*3302Smckusic int *typ, *idlist; 299*3302Smckusic int w, o; 300*3302Smckusic 301*3302Smckusic /* 302*3302Smckusic * Enter the parameters 303*3302Smckusic * and compute total size 304*3302Smckusic */ 305*3302Smckusic chainp = savedp = p; 306*3302Smckusic 307*3302Smckusic # ifdef OBJ 308*3302Smckusic o = 0; 309*3302Smckusic # endif OBJ 310*3302Smckusic # ifdef PC 311*3302Smckusic /* 312*3302Smckusic * parameters used to be allocated backwards, 313*3302Smckusic * then fixed. for pc, they are allocated correctly. 314*3302Smckusic * also, they are aligned. 315*3302Smckusic */ 316*3302Smckusic o = DPOFF2; 317*3302Smckusic # endif PC 318*3302Smckusic for (formalp = formalist; formalp != NIL; formalp = formalp[2]) { 319*3302Smckusic p = NIL; 320*3302Smckusic formal = formalp[1]; 321*3302Smckusic if (formal == NIL) 322*3302Smckusic continue; 323*3302Smckusic /* 324*3302Smckusic * Parametric procedures 325*3302Smckusic * don't have types !?! 326*3302Smckusic */ 327*3302Smckusic typ = formal[2]; 328*3302Smckusic if ( typ == NIL ) { 329*3302Smckusic if ( formal[0] != T_PPROC ) { 330*3302Smckusic error("Types must be specified for arguments"); 331*3302Smckusic p = NIL; 332*3302Smckusic } 333*3302Smckusic } else { 334*3302Smckusic if ( formal[0] == T_PPROC ) { 335*3302Smckusic error("Procedures cannot have types"); 336*3302Smckusic p = NIL; 337*3302Smckusic } else { 338*3302Smckusic if (typ[0] != T_TYID) { 339*3302Smckusic error("Types for arguments can be specified only by using type identifiers"); 340*3302Smckusic p = NIL; 341*3302Smckusic } else { 342*3302Smckusic p = gtype(typ); 343*3302Smckusic } 344*3302Smckusic } 345*3302Smckusic } 346*3302Smckusic for (idlist = formal[1]; idlist != NIL; idlist = idlist[2]) { 347*3302Smckusic switch (formal[0]) { 348*3302Smckusic default: 349*3302Smckusic panic("funchdr2"); 350*3302Smckusic case T_PVAL: 351*3302Smckusic if (p != NIL) { 352*3302Smckusic if (p->class == FILET) 353*3302Smckusic error("Files cannot be passed by value"); 354*3302Smckusic else if (p->nl_flags & NFILES) 355*3302Smckusic error("Files cannot be a component of %ss passed by value", 356*3302Smckusic nameof(p)); 357*3302Smckusic } 358*3302Smckusic # ifdef OBJ 359*3302Smckusic w = lwidth(p); 360*3302Smckusic o -= even(w); 361*3302Smckusic # ifdef DEC11 362*3302Smckusic dp = defnl(idlist[1], VAR, p, o); 363*3302Smckusic # else 364*3302Smckusic dp = defnl(idlist[1], VAR, p, 365*3302Smckusic (w < 2) ? o + 1 : o); 366*3302Smckusic # endif DEC11 367*3302Smckusic # endif OBJ 368*3302Smckusic # ifdef PC 369*3302Smckusic dp = defnl( idlist[1] , VAR , p 370*3302Smckusic , o = roundup( o , (long)A_STACK ) ); 371*3302Smckusic o += lwidth( p ); 372*3302Smckusic # endif PC 373*3302Smckusic dp->nl_flags |= NMOD; 374*3302Smckusic break; 375*3302Smckusic case T_PVAR: 376*3302Smckusic # ifdef OBJ 377*3302Smckusic dp = defnl(idlist[1], REF, p, o -= sizeof ( int * ) ); 378*3302Smckusic # endif OBJ 379*3302Smckusic # ifdef PC 380*3302Smckusic dp = defnl( idlist[1] , REF , p 381*3302Smckusic , o = roundup( o , (long)A_STACK ) ); 382*3302Smckusic o += sizeof(char *); 383*3302Smckusic # endif PC 384*3302Smckusic break; 385*3302Smckusic case T_PFUNC: 386*3302Smckusic if (idlist[2] != NIL) { 387*3302Smckusic error("Each function argument must be declared separately"); 388*3302Smckusic idlist[2] = NIL; 389*3302Smckusic } 390*3302Smckusic # ifdef OBJ 391*3302Smckusic dp = defnl(idlist[1], FFUNC, p, o -= sizeof ( int * ) ); 392*3302Smckusic # endif OBJ 393*3302Smckusic # ifdef PC 394*3302Smckusic dp = defnl( idlist[1] , FFUNC , p 395*3302Smckusic , o = roundup( o , (long)A_STACK ) ); 396*3302Smckusic o += sizeof(char *); 397*3302Smckusic # endif PC 398*3302Smckusic dp -> nl_flags |= NMOD; 399*3302Smckusic fparams(dp, formal); 400*3302Smckusic break; 401*3302Smckusic case T_PPROC: 402*3302Smckusic if (idlist[2] != NIL) { 403*3302Smckusic error("Each procedure argument must be declared separately"); 404*3302Smckusic idlist[2] = NIL; 405*3302Smckusic } 406*3302Smckusic # ifdef OBJ 407*3302Smckusic dp = defnl(idlist[1], FPROC, p, o -= sizeof ( int * ) ); 408*3302Smckusic # endif OBJ 409*3302Smckusic # ifdef PC 410*3302Smckusic dp = defnl( idlist[1] , FPROC , p 411*3302Smckusic , o = roundup( o , (long)A_STACK ) ); 412*3302Smckusic o += sizeof(char *); 413*3302Smckusic # endif PC 414*3302Smckusic dp -> nl_flags |= NMOD; 415*3302Smckusic fparams(dp, formal); 416*3302Smckusic break; 417*3302Smckusic } 418*3302Smckusic if (dp != NIL) { 419*3302Smckusic chainp->chain = dp; 420*3302Smckusic chainp = dp; 421*3302Smckusic } 422*3302Smckusic } 423*3302Smckusic } 424*3302Smckusic p = savedp; 425*3302Smckusic # ifdef OBJ 426*3302Smckusic /* 427*3302Smckusic * Correct the naivete (naivety) 428*3302Smckusic * of our above code to 429*3302Smckusic * calculate offsets 430*3302Smckusic */ 431*3302Smckusic for (dp = p->chain; dp != NIL; dp = dp->chain) 432*3302Smckusic dp->value[NL_OFFS] += -o + DPOFF2; 433*3302Smckusic return (-o + DPOFF2); 434*3302Smckusic # endif OBJ 435*3302Smckusic # ifdef PC 436*3302Smckusic return roundup( o , (long)A_STACK ); 437*3302Smckusic # endif PC 438*3302Smckusic } 439