|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1980 Regents of the University of California. ! 3: * All rights reserved. The Berkeley software License Agreement ! 4: * specifies the terms and conditions for redistribution. ! 5: */ ! 6: ! 7: #ifndef lint ! 8: static char sccsid[] = "@(#)fhdr.c 5.2 (Berkeley) 7/26/85"; ! 9: #endif not lint ! 10: ! 11: #include "whoami.h" ! 12: #include "0.h" ! 13: #include "tree.h" ! 14: #include "opcode.h" ! 15: #include "objfmt.h" ! 16: #include "align.h" ! 17: #include "tree_ty.h" ! 18: ! 19: /* ! 20: * this array keeps the pxp counters associated with ! 21: * functions and procedures, so that they can be output ! 22: * when their bodies are encountered ! 23: */ ! 24: int bodycnts[ DSPLYSZ ]; ! 25: ! 26: #ifdef PC ! 27: # include "pc.h" ! 28: #endif PC ! 29: ! 30: #ifdef OBJ ! 31: int cntpatch; ! 32: int nfppatch; ! 33: #endif OBJ ! 34: ! 35: /* ! 36: * Funchdr inserts ! 37: * declaration of a the ! 38: * prog/proc/func into the ! 39: * namelist. It also handles ! 40: * the arguments and puts out ! 41: * a transfer which defines ! 42: * the entry point of a procedure. ! 43: */ ! 44: ! 45: struct nl * ! 46: funchdr(r) ! 47: struct tnode *r; ! 48: { ! 49: register struct nl *p; ! 50: register struct tnode *rl; ! 51: struct nl *cp, *dp, *temp; ! 52: int o; ! 53: ! 54: if (inpflist(r->p_dec.id_ptr)) { ! 55: opush('l'); ! 56: yyretrieve(); /* kludge */ ! 57: } ! 58: pfcnt++; ! 59: parts[ cbn ] |= RPRT; ! 60: line = r->p_dec.line_no; ! 61: if (r->p_dec.param_list == TR_NIL && ! 62: (p=lookup1(r->p_dec.id_ptr)) != NIL && bn == cbn) { ! 63: /* ! 64: * Symbol already defined ! 65: * in this block. it is either ! 66: * a redeclared symbol (error) ! 67: * a forward declaration, ! 68: * or an external declaration. ! 69: * check that forwards are of the right kind: ! 70: * if this fails, we are trying to redefine it ! 71: * and enter() will complain. ! 72: */ ! 73: if ( ( ( p->nl_flags & NFORWD ) != 0 ) ! 74: && ( ( p->class == FUNC && r->tag == T_FDEC ) ! 75: || ( p->class == PROC && r->tag == T_PDEC ) ) ) { ! 76: /* ! 77: * Grammar doesnt forbid ! 78: * types on a resolution ! 79: * of a forward function ! 80: * declaration. ! 81: */ ! 82: if (p->class == FUNC && r->p_dec.type) ! 83: error("Function type should be given only in forward declaration"); ! 84: /* ! 85: * get another counter for the actual ! 86: */ ! 87: if ( monflg ) { ! 88: bodycnts[ cbn ] = getcnt(); ! 89: } ! 90: # ifdef PC ! 91: enclosing[ cbn ] = p -> symbol; ! 92: # endif PC ! 93: # ifdef PTREE ! 94: /* ! 95: * mark this proc/func as forward ! 96: * in the pTree. ! 97: */ ! 98: pDEF( p -> inTree ).PorFForward = TRUE; ! 99: # endif PTREE ! 100: return (p); ! 101: } ! 102: } ! 103: ! 104: /* if a routine segment is being compiled, ! 105: * do level one processing. ! 106: */ ! 107: ! 108: if ((r->tag != T_PROG) && (!progseen)) ! 109: level1(); ! 110: ! 111: ! 112: /* ! 113: * Declare the prog/proc/func ! 114: */ ! 115: switch (r->tag) { ! 116: case T_PROG: ! 117: progseen = TRUE; ! 118: if (opt('z')) ! 119: monflg = TRUE; ! 120: program = p = defnl(r->p_dec.id_ptr, PROG, NLNIL, 0); ! 121: p->value[3] = r->p_dec.line_no; ! 122: break; ! 123: case T_PDEC: ! 124: if (r->p_dec.type != TR_NIL) ! 125: error("Procedures do not have types, only functions do"); ! 126: p = enter(defnl(r->p_dec.id_ptr, PROC, NLNIL, 0)); ! 127: p->nl_flags |= NMOD; ! 128: # ifdef PC ! 129: enclosing[ cbn ] = r->p_dec.id_ptr; ! 130: p -> extra_flags |= NGLOBAL; ! 131: # endif PC ! 132: break; ! 133: case T_FDEC: ! 134: { ! 135: register struct tnode *il; ! 136: il = r->p_dec.type; ! 137: if (il == TR_NIL) { ! 138: temp = NLNIL; ! 139: error("Function type must be specified"); ! 140: } else if (il->tag != T_TYID) { ! 141: temp = NLNIL; ! 142: error("Function type can be specified only by using a type identifier"); ! 143: } else ! 144: temp = gtype(il); ! 145: } ! 146: p = enter(defnl(r->p_dec.id_ptr, FUNC, temp, NIL)); ! 147: p->nl_flags |= NMOD; ! 148: /* ! 149: * An arbitrary restriction ! 150: */ ! 151: switch (o = classify(p->type)) { ! 152: case TFILE: ! 153: case TARY: ! 154: case TREC: ! 155: case TSET: ! 156: case TSTR: ! 157: warning(); ! 158: if (opt('s')) { ! 159: standard(); ! 160: } ! 161: error("Functions should not return %ss", clnames[o]); ! 162: } ! 163: # ifdef PC ! 164: enclosing[ cbn ] = r->p_dec.id_ptr; ! 165: p -> extra_flags |= NGLOBAL; ! 166: # endif PC ! 167: break; ! 168: default: ! 169: panic("funchdr"); ! 170: } ! 171: if (r->tag != T_PROG) { ! 172: /* ! 173: * Mark this proc/func as ! 174: * being forward declared ! 175: */ ! 176: p->nl_flags |= NFORWD; ! 177: /* ! 178: * Enter the parameters ! 179: * in the next block for ! 180: * the time being ! 181: */ ! 182: if (++cbn >= DSPLYSZ) { ! 183: error("Procedure/function nesting too deep"); ! 184: pexit(ERRS); ! 185: } ! 186: /* ! 187: * For functions, the function variable ! 188: */ ! 189: if (p->class == FUNC) { ! 190: # ifdef OBJ ! 191: cp = defnl(r->p_dec.id_ptr, FVAR, p->type, 0); ! 192: # endif OBJ ! 193: # ifdef PC ! 194: /* ! 195: * fvars used to be allocated and deallocated ! 196: * by the caller right before the arguments. ! 197: * the offset of the fvar was kept in ! 198: * value[NL_OFFS] of function (very wierd, ! 199: * but see asgnop). ! 200: * now, they are locals to the function ! 201: * with the offset kept in the fvar. ! 202: */ ! 203: ! 204: cp = defnl(r->p_dec.id_ptr, FVAR, p->type, ! 205: (int)-leven(roundup( ! 206: (int)(DPOFF1+lwidth(p->type)), ! 207: (long)align(p->type)))); ! 208: cp -> extra_flags |= NLOCAL; ! 209: # endif PC ! 210: cp->chain = p; ! 211: p->ptr[NL_FVAR] = cp; ! 212: } ! 213: /* ! 214: * Enter the parameters ! 215: * and compute total size ! 216: */ ! 217: p->value[NL_OFFS] = params(p, r->p_dec.param_list); ! 218: /* ! 219: * because NL_LINENO field in the function ! 220: * namelist entry has been used (as have all ! 221: * the other fields), the line number is ! 222: * stored in the NL_LINENO field of its fvar. ! 223: */ ! 224: if (p->class == FUNC) ! 225: p->ptr[NL_FVAR]->value[NL_LINENO] = r->p_dec.line_no; ! 226: else ! 227: p->value[NL_LINENO] = r->p_dec.line_no; ! 228: cbn--; ! 229: } else { ! 230: /* ! 231: * The wonderful ! 232: * program statement! ! 233: */ ! 234: # ifdef OBJ ! 235: if (monflg) { ! 236: (void) put(1, O_PXPBUF); ! 237: cntpatch = put(2, O_CASE4, (long)0); ! 238: nfppatch = put(2, O_CASE4, (long)0); ! 239: } ! 240: # endif OBJ ! 241: cp = p; ! 242: for (rl = r->p_dec.param_list; rl; rl = rl->list_node.next) { ! 243: if (rl->list_node.list == TR_NIL) ! 244: continue; ! 245: dp = defnl((char *) rl->list_node.list, VAR, NLNIL, 0); ! 246: cp->chain = dp; ! 247: cp = dp; ! 248: } ! 249: } ! 250: /* ! 251: * Define a branch at ! 252: * the "entry point" of ! 253: * the prog/proc/func. ! 254: */ ! 255: p->value[NL_ENTLOC] = (int) getlab(); ! 256: if (monflg) { ! 257: bodycnts[ cbn ] = getcnt(); ! 258: p->value[ NL_CNTR ] = 0; ! 259: } ! 260: # ifdef OBJ ! 261: (void) put(2, O_TRA4, (long)p->value[NL_ENTLOC]); ! 262: # endif OBJ ! 263: # ifdef PTREE ! 264: { ! 265: pPointer PF = tCopy( r ); ! 266: ! 267: pSeize( PorFHeader[ nesting ] ); ! 268: if ( r->tag != T_PROG ) { ! 269: pPointer *PFs; ! 270: ! 271: PFs = &( pDEF( PorFHeader[ nesting ] ).PorFPFs ); ! 272: *PFs = ListAppend( *PFs , PF ); ! 273: } else { ! 274: pDEF( PorFHeader[ nesting ] ).GlobProg = PF; ! 275: } ! 276: pRelease( PorFHeader[ nesting ] ); ! 277: } ! 278: # endif PTREE ! 279: return (p); ! 280: } ! 281: ! 282: /* ! 283: * deal with the parameter declaration for a routine. ! 284: * p is the namelist entry of the routine. ! 285: * formalist is the parse tree for the parameter declaration. ! 286: * formalist [0] T_LISTPP ! 287: * [1] pointer to a formal ! 288: * [2] pointer to next formal ! 289: * for by-value or by-reference formals, the formal is ! 290: * formal [0] T_PVAL or T_PVAR ! 291: * [1] pointer to id_list ! 292: * [2] pointer to type (error if not typeid) ! 293: * for function and procedure formals, the formal is ! 294: * formal [0] T_PFUNC or T_PPROC ! 295: * [1] pointer to id_list (error if more than one) ! 296: * [2] pointer to type (error if not typeid, or proc) ! 297: * [3] pointer to formalist for this routine. ! 298: */ ! 299: fparams(p, formal) ! 300: register struct nl *p; ! 301: struct tnode *formal; /* T_PFUNC or T_PPROC */ ! 302: { ! 303: (void) params(p, formal->pfunc_node.param_list); ! 304: p -> value[ NL_LINENO ] = formal->pfunc_node.line_no; ! 305: p -> ptr[ NL_FCHAIN ] = p -> chain; ! 306: p -> chain = NIL; ! 307: } ! 308: ! 309: params(p, formalist) ! 310: register struct nl *p; ! 311: struct tnode *formalist; /* T_LISTPP */ ! 312: { ! 313: struct nl *chainp, *savedp; ! 314: struct nl *dp; ! 315: register struct tnode *formalp; /* an element of the formal list */ ! 316: register struct tnode *formal; /* a formal */ ! 317: struct tnode *r, *s, *t, *typ, *idlist; ! 318: int w, o; ! 319: ! 320: /* ! 321: * Enter the parameters ! 322: * and compute total size ! 323: */ ! 324: chainp = savedp = p; ! 325: ! 326: # ifdef OBJ ! 327: o = 0; ! 328: # endif OBJ ! 329: # ifdef PC ! 330: /* ! 331: * parameters used to be allocated backwards, ! 332: * then fixed. for pc, they are allocated correctly. ! 333: * also, they are aligned. ! 334: */ ! 335: o = DPOFF2; ! 336: # endif PC ! 337: for (formalp = formalist; formalp != TR_NIL; ! 338: formalp = formalp->list_node.next) { ! 339: formal = formalp->list_node.list; ! 340: if (formal == TR_NIL) ! 341: continue; ! 342: /* ! 343: * Parametric procedures ! 344: * don't have types !?! ! 345: */ ! 346: typ = formal->pfunc_node.type; ! 347: p = NLNIL; ! 348: if ( typ == TR_NIL ) { ! 349: if ( formal->tag != T_PPROC ) { ! 350: error("Types must be specified for arguments"); ! 351: } ! 352: } else { ! 353: if ( formal->tag == T_PPROC ) { ! 354: error("Procedures cannot have types"); ! 355: } else { ! 356: p = gtype(typ); ! 357: } ! 358: } ! 359: for (idlist = formal->param.id_list; idlist != TR_NIL; ! 360: idlist = idlist->list_node.next) { ! 361: switch (formal->tag) { ! 362: default: ! 363: panic("funchdr2"); ! 364: case T_PVAL: ! 365: if (p != NLNIL) { ! 366: if (p->class == FILET) ! 367: error("Files cannot be passed by value"); ! 368: else if (p->nl_flags & NFILES) ! 369: error("Files cannot be a component of %ss passed by value", ! 370: nameof(p)); ! 371: } ! 372: # ifdef OBJ ! 373: w = lwidth(p); ! 374: o -= even(w); ! 375: # ifdef DEC11 ! 376: dp = defnl((char *) idlist->list_node.list, ! 377: VAR, p, o); ! 378: # else ! 379: dp = defnl((char *) idlist->list_node.list, ! 380: VAR,p, (w < 2) ? o + 1 : o); ! 381: # endif DEC11 ! 382: # endif OBJ ! 383: # ifdef PC ! 384: o = roundup(o, (long) A_STACK); ! 385: w = lwidth(p); ! 386: # ifndef DEC11 ! 387: if (w <= sizeof(int)) { ! 388: o += sizeof(int) - w; ! 389: } ! 390: # endif not DEC11 ! 391: dp = defnl((char *) idlist->list_node.list,VAR, ! 392: p, o); ! 393: o += w; ! 394: # endif PC ! 395: dp->nl_flags |= NMOD; ! 396: break; ! 397: case T_PVAR: ! 398: # ifdef OBJ ! 399: dp = defnl((char *) idlist->list_node.list, REF, ! 400: p, o -= sizeof ( int * ) ); ! 401: # endif OBJ ! 402: # ifdef PC ! 403: dp = defnl( (char *) idlist->list_node.list, REF, ! 404: p , ! 405: o = roundup( o , (long)A_STACK ) ); ! 406: o += sizeof(char *); ! 407: # endif PC ! 408: break; ! 409: case T_PFUNC: ! 410: if (idlist->list_node.next != TR_NIL) { ! 411: error("Each function argument must be declared separately"); ! 412: idlist->list_node.next = TR_NIL; ! 413: } ! 414: # ifdef OBJ ! 415: dp = defnl((char *) idlist->list_node.list,FFUNC, ! 416: p, o -= sizeof ( int * ) ); ! 417: # endif OBJ ! 418: # ifdef PC ! 419: dp = defnl( (char *) idlist->list_node.list , ! 420: FFUNC , p , ! 421: o = roundup( o , (long)A_STACK ) ); ! 422: o += sizeof(char *); ! 423: # endif PC ! 424: dp -> nl_flags |= NMOD; ! 425: fparams(dp, formal); ! 426: break; ! 427: case T_PPROC: ! 428: if (idlist->list_node.next != TR_NIL) { ! 429: error("Each procedure argument must be declared separately"); ! 430: idlist->list_node.next = TR_NIL; ! 431: } ! 432: # ifdef OBJ ! 433: dp = defnl((char *) idlist->list_node.list, ! 434: FPROC, p, o -= sizeof ( int * ) ); ! 435: # endif OBJ ! 436: # ifdef PC ! 437: dp = defnl( (char *) idlist->list_node.list , ! 438: FPROC , p, ! 439: o = roundup( o , (long)A_STACK ) ); ! 440: o += sizeof(char *); ! 441: # endif PC ! 442: dp -> nl_flags |= NMOD; ! 443: fparams(dp, formal); ! 444: break; ! 445: } ! 446: if (dp != NLNIL) { ! 447: # ifdef PC ! 448: dp -> extra_flags |= NPARAM; ! 449: # endif PC ! 450: chainp->chain = dp; ! 451: chainp = dp; ! 452: } ! 453: } ! 454: if (typ != TR_NIL && typ->tag == T_TYCARY) { ! 455: # ifdef OBJ ! 456: w = -even(lwidth(p->chain)); ! 457: # ifndef DEC11 ! 458: w = (w > -2)? w + 1 : w; ! 459: # endif ! 460: # endif OBJ ! 461: # ifdef PC ! 462: w = lwidth(p->chain); ! 463: o = roundup(o, (long)A_STACK); ! 464: # endif PC ! 465: /* ! 466: * Allocate space for upper and ! 467: * lower bounds and width. ! 468: */ ! 469: for (s=typ; s->tag == T_TYCARY; s = s->ary_ty.type) { ! 470: for (r=s->ary_ty.type_list; r != TR_NIL; ! 471: r = r->list_node.next) { ! 472: t = r->list_node.list; ! 473: p = p->chain; ! 474: # ifdef OBJ ! 475: o += w; ! 476: # endif OBJ ! 477: chainp->chain = defnl(t->crang_ty.lwb_var, ! 478: VAR, p, o); ! 479: chainp = chainp->chain; ! 480: chainp->nl_flags |= (NMOD | NUSED); ! 481: p->nptr[0] = chainp; ! 482: o += w; ! 483: chainp->chain = defnl(t->crang_ty.upb_var, ! 484: VAR, p, o); ! 485: chainp = chainp->chain; ! 486: chainp->nl_flags |= (NMOD | NUSED); ! 487: p->nptr[1] = chainp; ! 488: o += w; ! 489: chainp->chain = defnl(0, VAR, p, o); ! 490: chainp = chainp->chain; ! 491: chainp->nl_flags |= (NMOD | NUSED); ! 492: p->nptr[2] = chainp; ! 493: # ifdef PC ! 494: o += w; ! 495: # endif PC ! 496: } ! 497: } ! 498: } ! 499: } ! 500: p = savedp; ! 501: # ifdef OBJ ! 502: /* ! 503: * Correct the naivete (naivety) ! 504: * of our above code to ! 505: * calculate offsets ! 506: */ ! 507: for (dp = p->chain; dp != NLNIL; dp = dp->chain) ! 508: dp->value[NL_OFFS] += -o + DPOFF2; ! 509: return (-o + DPOFF2); ! 510: # endif OBJ ! 511: # ifdef PC ! 512: return roundup( o , (long)A_STACK ); ! 513: # endif PC ! 514: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.