1 /* Copyright (c) 1979 Regents of the University of California */ 2 3 static char sccsid[] = "@(#)fdec.c 1.13 01/24/81"; 4 5 #include "whoami.h" 6 #include "0.h" 7 #include "tree.h" 8 #include "opcode.h" 9 #include "objfmt.h" 10 #include "align.h" 11 12 /* 13 * this array keeps the pxp counters associated with 14 * functions and procedures, so that they can be output 15 * when their bodies are encountered 16 */ 17 int bodycnts[ DSPLYSZ ]; 18 19 #ifdef PC 20 # include "pc.h" 21 # include "pcops.h" 22 #endif PC 23 24 #ifdef OBJ 25 int cntpatch; 26 int nfppatch; 27 #endif OBJ 28 29 /* 30 * Funchdr inserts 31 * declaration of a the 32 * prog/proc/func into the 33 * namelist. It also handles 34 * the arguments and puts out 35 * a transfer which defines 36 * the entry point of a procedure. 37 */ 38 39 struct nl * 40 funchdr(r) 41 int *r; 42 { 43 register struct nl *p; 44 register *il, **rl; 45 int *rll; 46 struct nl *cp, *dp, *sp; 47 int s, o, *pp; 48 49 if (inpflist(r[2])) { 50 opush('l'); 51 yyretrieve(); /* kludge */ 52 } 53 pfcnt++; 54 parts[ cbn ] |= RPRT; 55 line = r[1]; 56 if (r[3] == NIL && (p=lookup1(r[2])) != NIL && bn == cbn) { 57 /* 58 * Symbol already defined 59 * in this block. it is either 60 * a redeclared symbol (error) 61 * a forward declaration, 62 * or an external declaration. 63 */ 64 if ((p->class == FUNC || p->class == PROC) && (p->nl_flags & NFORWD) != 0) { 65 /* 66 * Grammar doesnt forbid 67 * types on a resolution 68 * of a forward function 69 * declaration. 70 */ 71 if (p->class == FUNC && r[4]) 72 error("Function type should be given only in forward declaration"); 73 /* 74 * get another counter for the actual 75 */ 76 if ( monflg ) { 77 bodycnts[ cbn ] = getcnt(); 78 } 79 # ifdef PC 80 enclosing[ cbn ] = p -> symbol; 81 # endif PC 82 # ifdef PTREE 83 /* 84 * mark this proc/func as forward 85 * in the pTree. 86 */ 87 pDEF( p -> inTree ).PorFForward = TRUE; 88 # endif PTREE 89 return (p); 90 } 91 } 92 93 /* if a routine segment is being compiled, 94 * do level one processing. 95 */ 96 97 if ((r[0] != T_PROG) && (!progseen)) 98 level1(); 99 100 101 /* 102 * Declare the prog/proc/func 103 */ 104 switch (r[0]) { 105 case T_PROG: 106 progseen++; 107 if (opt('z')) 108 monflg++; 109 program = p = defnl(r[2], PROG, 0, 0); 110 p->value[3] = r[1]; 111 break; 112 case T_PDEC: 113 if (r[4] != NIL) 114 error("Procedures do not have types, only functions do"); 115 p = enter(defnl(r[2], PROC, 0, 0)); 116 p->nl_flags |= NMOD; 117 # ifdef PC 118 enclosing[ cbn ] = r[2]; 119 # endif PC 120 break; 121 case T_FDEC: 122 il = r[4]; 123 if (il == NIL) 124 error("Function type must be specified"); 125 else if (il[0] != T_TYID) { 126 il = NIL; 127 error("Function type can be specified only by using a type identifier"); 128 } else 129 il = gtype(il); 130 p = enter(defnl(r[2], FUNC, il, NIL)); 131 p->nl_flags |= NMOD; 132 /* 133 * An arbitrary restriction 134 */ 135 switch (o = classify(p->type)) { 136 case TFILE: 137 case TARY: 138 case TREC: 139 case TSET: 140 case TSTR: 141 warning(); 142 if (opt('s')) { 143 standard(); 144 } 145 error("Functions should not return %ss", clnames[o]); 146 } 147 # ifdef PC 148 enclosing[ cbn ] = r[2]; 149 # endif PC 150 break; 151 default: 152 panic("funchdr"); 153 } 154 if (r[0] != T_PROG) { 155 /* 156 * Mark this proc/func as 157 * being forward declared 158 */ 159 p->nl_flags |= NFORWD; 160 /* 161 * Enter the parameters 162 * in the next block for 163 * the time being 164 */ 165 if (++cbn >= DSPLYSZ) { 166 error("Procedure/function nesting too deep"); 167 pexit(ERRS); 168 } 169 /* 170 * For functions, the function variable 171 */ 172 if (p->class == FUNC) { 173 # ifdef OBJ 174 cp = defnl(r[2], FVAR, p->type, 0); 175 # endif OBJ 176 # ifdef PC 177 /* 178 * fvars used to be allocated and deallocated 179 * by the caller right before the arguments. 180 * the offset of the fvar was kept in 181 * value[NL_OFFS] of function (very wierd, 182 * but see asgnop). 183 * now, they are locals to the function 184 * with the offset kept in the fvar. 185 */ 186 187 cp = defnl( r[2] , FVAR , p -> type 188 , -( roundup( DPOFF1+width( p -> type ) 189 , align( p -> type ) ) ) ); 190 # endif PC 191 cp->chain = p; 192 p->ptr[NL_FVAR] = cp; 193 } 194 /* 195 * Enter the parameters 196 * and compute total size 197 */ 198 cp = sp = p; 199 200 # ifdef OBJ 201 o = 0; 202 # endif OBJ 203 # ifdef PC 204 /* 205 * parameters used to be allocated backwards, 206 * then fixed. for pc, they are allocated correctly. 207 * also, they are aligned. 208 */ 209 o = DPOFF2; 210 # endif PC 211 for (rl = r[3]; rl != NIL; rl = rl[2]) { 212 p = NIL; 213 if (rl[1] == NIL) 214 continue; 215 /* 216 * Parametric procedures 217 * don't have types !?! 218 */ 219 if (rl[1][0] != T_PPROC) { 220 rll = rl[1][2]; 221 if (rll[0] != T_TYID) { 222 error("Types for arguments can be specified only by using type identifiers"); 223 p = NIL; 224 } else 225 p = gtype(rll); 226 } 227 for (il = rl[1][1]; il != NIL; il = il[2]) { 228 switch (rl[1][0]) { 229 default: 230 panic("funchdr2"); 231 case T_PVAL: 232 if (p != NIL) { 233 if (p->class == FILET) 234 error("Files cannot be passed by value"); 235 else if (p->nl_flags & NFILES) 236 error("Files cannot be a component of %ss passed by value", 237 nameof(p)); 238 } 239 # ifdef OBJ 240 dp = defnl(il[1], VAR, p, o -= even(width(p))); 241 # endif OBJ 242 # ifdef PC 243 dp = defnl( il[1] , VAR , p 244 , o = roundup( o , A_STACK ) ); 245 o += width( p ); 246 # endif PC 247 dp->nl_flags |= NMOD; 248 break; 249 case T_PVAR: 250 # ifdef OBJ 251 dp = defnl(il[1], REF, p, o -= sizeof ( int * ) ); 252 # endif OBJ 253 # ifdef PC 254 dp = defnl( il[1] , REF , p 255 , o = roundup( o , A_STACK ) ); 256 o += sizeof(char *); 257 # endif PC 258 break; 259 case T_PFUNC: 260 # ifdef OBJ 261 dp = defnl(il[1], FFUNC, p, o -= sizeof ( int * ) ); 262 # endif OBJ 263 # ifdef PC 264 dp = defnl( il[1] , FFUNC , p 265 , o = roundup( o , A_STACK ) ); 266 o += sizeof(char *); 267 # endif PC 268 dp -> nl_flags |= NMOD; 269 break; 270 case T_PPROC: 271 # ifdef OBJ 272 dp = defnl(il[1], FPROC, p, o -= sizeof ( int * ) ); 273 # endif OBJ 274 # ifdef PC 275 dp = defnl( il[1] , FPROC , p 276 , o = roundup( o , A_STACK ) ); 277 o += sizeof(char *); 278 # endif PC 279 dp -> nl_flags |= NMOD; 280 break; 281 } 282 if (dp != NIL) { 283 cp->chain = dp; 284 cp = dp; 285 } 286 } 287 } 288 cbn--; 289 p = sp; 290 # ifdef OBJ 291 p->value[NL_OFFS] = -o+DPOFF2; 292 /* 293 * Correct the naivete (naievity) 294 * of our above code to 295 * calculate offsets 296 */ 297 for (il = p->chain; il != NIL; il = il->chain) 298 il->value[NL_OFFS] += p->value[NL_OFFS]; 299 # endif OBJ 300 # ifdef PC 301 p -> value[ NL_OFFS ] = roundup( o , A_STACK ); 302 # endif PC 303 } else { 304 /* 305 * The wonderful 306 * program statement! 307 */ 308 # ifdef OBJ 309 if (monflg) { 310 put(1, O_PXPBUF); 311 cntpatch = put(2, O_CASE4, 0); 312 nfppatch = put(2, O_CASE4, 0); 313 } 314 # endif OBJ 315 cp = p; 316 for (rl = r[3]; rl; rl = rl[2]) { 317 if (rl[1] == NIL) 318 continue; 319 dp = defnl(rl[1], VAR, 0, 0); 320 cp->chain = dp; 321 cp = dp; 322 } 323 } 324 /* 325 * Define a branch at 326 * the "entry point" of 327 * the prog/proc/func. 328 */ 329 p->entloc = getlab(); 330 if (monflg) { 331 bodycnts[ cbn ] = getcnt(); 332 p->value[ NL_CNTR ] = 0; 333 } 334 # ifdef OBJ 335 put(2, O_TRA4, p->entloc); 336 # endif OBJ 337 # ifdef PTREE 338 { 339 pPointer PF = tCopy( r ); 340 341 pSeize( PorFHeader[ nesting ] ); 342 if ( r[0] != T_PROG ) { 343 pPointer *PFs; 344 345 PFs = &( pDEF( PorFHeader[ nesting ] ).PorFPFs ); 346 *PFs = ListAppend( *PFs , PF ); 347 } else { 348 pDEF( PorFHeader[ nesting ] ).GlobProg = PF; 349 } 350 pRelease( PorFHeader[ nesting ] ); 351 } 352 # endif PTREE 353 return (p); 354 } 355 356 funcfwd(fp) 357 struct nl *fp; 358 { 359 360 /* 361 * save the counter for this function 362 */ 363 if ( monflg ) { 364 fp -> value[ NL_CNTR ] = bodycnts[ cbn ]; 365 } 366 return (fp); 367 } 368 369 /* 370 * Funcext marks the procedure or 371 * function external in the symbol 372 * table. Funcext should only be 373 * called if PC, and is an error 374 * otherwise. 375 */ 376 377 funcext(fp) 378 struct nl *fp; 379 { 380 381 #ifdef PC 382 if (opt('s')) { 383 standard(); 384 error("External procedures and functions are not standard"); 385 } else { 386 if (cbn == 1) { 387 fp->ext_flags |= NEXTERN; 388 stabefunc( fp -> symbol , fp -> class , line ); 389 } 390 else 391 error("External procedures and functions can only be declared at the outermost level."); 392 } 393 #endif PC 394 #ifdef OBJ 395 error("Procedures or functions cannot be declared external."); 396 #endif OBJ 397 398 return(fp); 399 } 400 401 /* 402 * Funcbody is called 403 * when the actual (resolved) 404 * declaration of a procedure is 405 * encountered. It puts the names 406 * of the (function) and parameters 407 * into the symbol table. 408 */ 409 funcbody(fp) 410 struct nl *fp; 411 { 412 register struct nl *q, *p; 413 414 cbn++; 415 if (cbn >= DSPLYSZ) { 416 error("Too many levels of function/procedure nesting"); 417 pexit(ERRS); 418 } 419 sizes[cbn].om_max = sizes[cbn].om_off = -DPOFF1; 420 gotos[cbn] = NIL; 421 errcnt[cbn] = syneflg; 422 parts[ cbn ] = NIL; 423 dfiles[ cbn ] = FALSE; 424 if (fp == NIL) 425 return (NIL); 426 /* 427 * Save the virtual name 428 * list stack pointer so 429 * the space can be freed 430 * later (funcend). 431 */ 432 fp->ptr[2] = nlp; 433 if (fp->class != PROG) { 434 for (q = fp->chain; q != NIL; q = q->chain) { 435 enter(q); 436 } 437 } 438 if (fp->class == FUNC) { 439 /* 440 * For functions, enter the fvar 441 */ 442 enter(fp->ptr[NL_FVAR]); 443 # ifdef PC 444 q = fp -> ptr[ NL_FVAR ]; 445 sizes[cbn].om_off -= lwidth( q -> type ); 446 sizes[cbn].om_max = sizes[cbn].om_off; 447 # endif PC 448 } 449 # ifdef PTREE 450 /* 451 * pick up the pointer to porf declaration 452 */ 453 PorFHeader[ ++nesting ] = fp -> inTree; 454 # endif PTREE 455 return (fp); 456 } 457 458 struct nl *Fp; 459 int pnumcnt; 460 /* 461 * Funcend is called to 462 * finish a block by generating 463 * the code for the statements. 464 * It then looks for unresolved declarations 465 * of labels, procedures and functions, 466 * and cleans up the name list. 467 * For the program, it checks the 468 * semantics of the program 469 * statement (yuchh). 470 */ 471 funcend(fp, bundle, endline) 472 struct nl *fp; 473 int *bundle; 474 int endline; 475 { 476 register struct nl *p; 477 register int i, b; 478 int var, inp, out, chkref, *blk; 479 struct nl *iop; 480 char *cp; 481 extern int cntstat; 482 # ifdef PC 483 int toplabel = getlab(); 484 int botlabel = getlab(); 485 # endif PC 486 487 cntstat = 0; 488 /* 489 * yyoutline(); 490 */ 491 if (program != NIL) 492 line = program->value[3]; 493 blk = bundle[2]; 494 if (fp == NIL) { 495 cbn--; 496 # ifdef PTREE 497 nesting--; 498 # endif PTREE 499 return; 500 } 501 #ifdef OBJ 502 /* 503 * Patch the branch to the 504 * entry point of the function 505 */ 506 patch4(fp->entloc); 507 /* 508 * Put out the block entrance code and the block name. 509 * HDRSZE is the number of bytes of info in the static 510 * BEG data area exclusive of the proc name. It is 511 * currently defined as: 512 /* struct hdr { 513 /* long framesze; /* number of bytes of local vars */ 514 /* long nargs; /* number of bytes of arguments */ 515 /* short tests; /* TRUE => perform runtime tests */ 516 /* short offset; /* offset of procedure in source file */ 517 /* char name[1]; /* name of active procedure */ 518 /* }; 519 */ 520 # define HDRSZE 12 521 var = put(2, (lenstr(fp->symbol,0) + HDRSZE << 8) 522 | (cbn == 1 && opt('p') == 0 ? O_NODUMP: O_BEG), 0); 523 /* 524 * output the number of bytes of arguments 525 * this is only checked on formal calls. 526 */ 527 put(2, O_CASE4, cbn == 1 ? 0 : fp->value[NL_OFFS]-DPOFF2); 528 /* 529 * Output the runtime test mode for the routine 530 */ 531 if (opt('t')) 532 put(2, O_CASE2, TRUE); 533 else 534 put(2, O_CASE2, FALSE); 535 /* 536 * Output line number and routine name 537 */ 538 put(2, O_CASE2, bundle[1]); 539 putstr(fp->symbol, 0); 540 #endif OBJ 541 #ifdef PC 542 /* 543 * put out the procedure entry code 544 */ 545 if ( fp -> class == PROG ) { 546 putprintf( " .text" , 0 ); 547 putprintf( " .align 1" , 0 ); 548 putprintf( " .globl _main" , 0 ); 549 putprintf( "_main:" , 0 ); 550 putprintf( " .word 0" , 0 ); 551 putprintf( " calls $0,_PCSTART" , 0 ); 552 putprintf( " movl 4(ap),__argc" , 0 ); 553 putprintf( " movl 8(ap),__argv" , 0 ); 554 putprintf( " calls $0,_program" , 0 ); 555 putprintf( " calls $0,_PCEXIT" , 0 ); 556 ftnno = fp -> entloc; 557 putprintf( " .text" , 0 ); 558 putprintf( " .align 1" , 0 ); 559 putprintf( " .globl _program" , 0 ); 560 putprintf( "_program:" , 0 ); 561 stabfunc( "program" , fp -> class , bundle[1] , 0 ); 562 } else { 563 ftnno = fp -> entloc; 564 putprintf( " .text" , 0 ); 565 putprintf( " .align 1" , 0 ); 566 putprintf( " .globl " , 1 ); 567 for ( i = 1 ; i < cbn ; i++ ) { 568 putprintf( EXTFORMAT , 1 , enclosing[ i ] ); 569 } 570 putprintf( "" , 0 ); 571 for ( i = 1 ; i < cbn ; i++ ) { 572 putprintf( EXTFORMAT , 1 , enclosing[ i ] ); 573 } 574 putprintf( ":" , 0 ); 575 stabfunc( fp -> symbol , fp -> class , bundle[1] , cbn - 1 ); 576 for ( p = fp -> chain ; p != NIL ; p = p -> chain ) { 577 stabparam( p -> symbol , p2type( p -> type ) 578 , p -> value[ NL_OFFS ] , lwidth( p -> type ) ); 579 } 580 if ( fp -> class == FUNC ) { 581 /* 582 * stab the function variable 583 */ 584 p = fp -> ptr[ NL_FVAR ]; 585 stablvar( p -> symbol , p2type( p -> type ) , cbn 586 , p -> value[ NL_OFFS ] , lwidth( p -> type ) ); 587 } 588 /* 589 * stab local variables 590 * rummage down hash chain links. 591 */ 592 for ( i = 0 ; i <= 077 ; i++ ) { 593 for ( p = disptab[ i ] ; p != NIL ; p = p->nl_next) { 594 if ( ( p -> nl_block & 037 ) != cbn ) { 595 break; 596 } 597 /* 598 * stab local variables 599 * that's named variables, but not params 600 */ 601 if ( ( p -> symbol != NIL ) 602 && ( p -> class == VAR ) 603 && ( p -> value[ NL_OFFS ] < 0 ) ) { 604 stablvar( p -> symbol , p2type( p -> type ) , cbn 605 , p -> value[ NL_OFFS ] , lwidth( p -> type ) ); 606 } 607 } 608 } 609 } 610 stablbrac( cbn ); 611 /* 612 * register save mask 613 */ 614 if ( opt( 't' ) ) { 615 putprintf( " .word 0x%x" , 0 , RUNCHECK | RSAVEMASK ); 616 } else { 617 putprintf( " .word 0x%x" , 0 , RSAVEMASK ); 618 } 619 putjbr( botlabel ); 620 putlab( toplabel ); 621 if ( profflag ) { 622 /* 623 * call mcount for profiling 624 */ 625 putprintf( " moval 1f,r0" , 0 ); 626 putprintf( " jsb mcount" , 0 ); 627 putprintf( " .data" , 0 ); 628 putprintf( " .align 2" , 0 ); 629 putprintf( "1:" , 0 ); 630 putprintf( " .long 0" , 0 ); 631 putprintf( " .text" , 0 ); 632 } 633 /* 634 * set up unwind exception vector. 635 */ 636 putprintf( " moval %s,%d(%s)" , 0 637 , UNWINDNAME , UNWINDOFFSET , P2FPNAME ); 638 /* 639 * save address of display entry, for unwind. 640 */ 641 putprintf( " moval %s+%d,%d(%s)" , 0 642 , DISPLAYNAME , cbn * sizeof(struct dispsave) 643 , DPTROFFSET , P2FPNAME ); 644 /* 645 * save old display 646 */ 647 putprintf( " movq %s+%d,%d(%s)" , 0 648 , DISPLAYNAME , cbn * sizeof(struct dispsave) 649 , DSAVEOFFSET , P2FPNAME ); 650 /* 651 * set up new display by saving AP and FP in appropriate 652 * slot in display structure. 653 */ 654 putprintf( " movq %s,%s+%d" , 0 655 , P2APNAME , DISPLAYNAME , cbn * sizeof(struct dispsave) ); 656 /* 657 * ask second pass to allocate known locals 658 */ 659 putlbracket( ftnno , -sizes[ cbn ].om_max ); 660 /* 661 * and zero them if checking is on 662 * by calling blkclr( bytes of locals , starting local address ); 663 */ 664 if ( opt( 't' ) ) { 665 if ( ( -sizes[ cbn ].om_max ) > DPOFF1 ) { 666 putleaf( P2ICON , 0 , 0 , ADDTYPE( P2FTN | P2INT , P2PTR ) 667 , "_blkclr" ); 668 putleaf( P2ICON , ( -sizes[ cbn ].om_max ) - DPOFF1 669 , 0 , P2INT , 0 ); 670 putLV( 0 , cbn , sizes[ cbn ].om_max , P2CHAR ); 671 putop( P2LISTOP , P2INT ); 672 putop( P2CALL , P2INT ); 673 putdot( filename , line ); 674 } 675 /* 676 * check number of longs of arguments 677 * this can only be wrong for formal calls. 678 */ 679 if ( fp -> class != PROG ) { 680 putleaf( P2ICON , 0 , 0 , ADDTYPE( P2PTR , P2FTN | P2INT ) , 681 "_NARGCHK" ); 682 putleaf( P2ICON , 683 (fp->value[NL_OFFS] - DPOFF2) / sizeof(long) , 684 0 , P2INT , 0 ); 685 putop( P2CALL , P2INT ); 686 putdot( filename , line ); 687 } 688 } 689 #endif PC 690 if ( monflg ) { 691 if ( fp -> value[ NL_CNTR ] != 0 ) { 692 inccnt( fp -> value [ NL_CNTR ] ); 693 } 694 inccnt( bodycnts[ fp -> nl_block & 037 ] ); 695 } 696 if (fp->class == PROG) { 697 /* 698 * The glorious buffers option. 699 * 0 = don't buffer output 700 * 1 = line buffer output 701 * 2 = 512 byte buffer output 702 */ 703 # ifdef OBJ 704 if (opt('b') != 1) 705 put(1, O_BUFF | opt('b') << 8); 706 # endif OBJ 707 # ifdef PC 708 if ( opt( 'b' ) != 1 ) { 709 putleaf( P2ICON , 0 , 0 710 , ADDTYPE( P2FTN | P2INT , P2PTR ) , "_BUFF" ); 711 putleaf( P2ICON , opt( 'b' ) , 0 , P2INT , 0 ); 712 putop( P2CALL , P2INT ); 713 putdot( filename , line ); 714 } 715 # endif PC 716 out = 0; 717 for (p = fp->chain; p != NIL; p = p->chain) { 718 if (strcmp(p->symbol, "input") == 0) { 719 inp++; 720 continue; 721 } 722 if (strcmp(p->symbol, "output") == 0) { 723 out++; 724 continue; 725 } 726 iop = lookup1(p->symbol); 727 if (iop == NIL || bn != cbn) { 728 error("File %s listed in program statement but not declared", p->symbol); 729 continue; 730 } 731 if (iop->class != VAR) { 732 error("File %s listed in program statement but declared as a %s", p->symbol, classes[iop->class]); 733 continue; 734 } 735 if (iop->type == NIL) 736 continue; 737 if (iop->type->class != FILET) { 738 error("File %s listed in program statement but defined as %s", 739 p->symbol, nameof(iop->type)); 740 continue; 741 } 742 # ifdef OBJ 743 put(2, O_CON24, text(iop->type) ? 0 : width(iop->type->type)); 744 i = lenstr(p->symbol,0); 745 put(2, O_CON24, i); 746 put(2, O_LVCON, i); 747 putstr(p->symbol, 0); 748 put(2, O_LV | bn << 8+INDX, iop->value[NL_OFFS]); 749 put(1, O_DEFNAME); 750 # endif OBJ 751 # ifdef PC 752 putleaf( P2ICON , 0 , 0 753 , ADDTYPE( P2FTN | P2INT , P2PTR ) 754 , "_DEFNAME" ); 755 putLV( p -> symbol , bn , iop -> value[NL_OFFS] 756 , p2type( iop ) ); 757 putCONG( p -> symbol , strlen( p -> symbol ) 758 , LREQ ); 759 putop( P2LISTOP , P2INT ); 760 putleaf( P2ICON , strlen( p -> symbol ) 761 , 0 , P2INT , 0 ); 762 putop( P2LISTOP , P2INT ); 763 putleaf( P2ICON 764 , text(iop->type) ? 0 : width(iop->type->type) 765 , 0 , P2INT , 0 ); 766 putop( P2LISTOP , P2INT ); 767 putop( P2CALL , P2INT ); 768 putdot( filename , line ); 769 # endif PC 770 } 771 if (out == 0 && fp->chain != NIL) { 772 recovered(); 773 error("The file output must appear in the program statement file list"); 774 } 775 } 776 /* 777 * Process the prog/proc/func body 778 */ 779 noreach = 0; 780 line = bundle[1]; 781 statlist(blk); 782 # ifdef PTREE 783 { 784 pPointer Body = tCopy( blk ); 785 786 pDEF( PorFHeader[ nesting -- ] ).PorFBody = Body; 787 } 788 # endif PTREE 789 # ifdef OBJ 790 if (cbn== 1 && monflg != 0) { 791 patchfil(cntpatch - 2, cnts, 2); 792 patchfil(nfppatch - 2, pfcnt, 2); 793 } 794 # endif OBJ 795 # ifdef PC 796 if ( fp -> class == PROG && monflg ) { 797 putleaf( P2ICON , 0 , 0 , ADDTYPE( P2FTN | P2INT , P2PTR ) 798 , "_PMFLUSH" ); 799 putleaf( P2ICON , cnts , 0 , P2INT , 0 ); 800 putleaf( P2ICON , pfcnt , 0 , P2INT , 0 ); 801 putop( P2LISTOP , P2INT ); 802 putLV( PCPCOUNT , 0 , 0 , P2INT ); 803 putop( P2LISTOP , P2INT ); 804 putop( P2CALL , P2INT ); 805 putdot( filename , line ); 806 } 807 # endif PC 808 if (fp->class == PROG && inp == 0 && (input->nl_flags & (NUSED|NMOD)) != 0) { 809 recovered(); 810 error("Input is used but not defined in the program statement"); 811 } 812 /* 813 * Clean up the symbol table displays and check for unresolves 814 */ 815 line = endline; 816 b = cbn; 817 Fp = fp; 818 chkref = syneflg == errcnt[cbn] && opt('w') == 0; 819 for (i = 0; i <= 077; i++) { 820 for (p = disptab[i]; p != NIL && (p->nl_block & 037) == b; p = p->nl_next) { 821 /* 822 * Check for variables defined 823 * but not referenced 824 */ 825 if (chkref && p->symbol != NIL) 826 switch (p->class) { 827 case FIELD: 828 /* 829 * If the corresponding record is 830 * unused, we shouldn't complain about 831 * the fields. 832 */ 833 default: 834 if ((p->nl_flags & (NUSED|NMOD)) == 0) { 835 warning(); 836 nerror("%s %s is neither used nor set", classes[p->class], p->symbol); 837 break; 838 } 839 /* 840 * If a var parameter is either 841 * modified or used that is enough. 842 */ 843 if (p->class == REF) 844 continue; 845 # ifdef OBJ 846 if ((p->nl_flags & NUSED) == 0) { 847 warning(); 848 nerror("%s %s is never used", classes[p->class], p->symbol); 849 break; 850 } 851 # endif OBJ 852 # ifdef PC 853 if (((p->nl_flags & NUSED) == 0) && ((p->ext_flags & NEXTERN) == 0)) { 854 warning(); 855 nerror("%s %s is never used", classes[p->class], p->symbol); 856 break; 857 } 858 # endif PC 859 if ((p->nl_flags & NMOD) == 0) { 860 warning(); 861 nerror("%s %s is used but never set", classes[p->class], p->symbol); 862 break; 863 } 864 case LABEL: 865 case FVAR: 866 case BADUSE: 867 break; 868 } 869 switch (p->class) { 870 case BADUSE: 871 cp = "s"; 872 if (p->chain->ud_next == NIL) 873 cp++; 874 eholdnl(); 875 if (p->value[NL_KINDS] & ISUNDEF) 876 nerror("%s undefined on line%s", p->symbol, cp); 877 else 878 nerror("%s improperly used on line%s", p->symbol, cp); 879 pnumcnt = 10; 880 pnums(p->chain); 881 pchr('\n'); 882 break; 883 884 case FUNC: 885 case PROC: 886 # ifdef OBJ 887 if ((p->nl_flags & NFORWD)) 888 nerror("Unresolved forward declaration of %s %s", classes[p->class], p->symbol); 889 # endif OBJ 890 # ifdef PC 891 if ((p->nl_flags & NFORWD) && ((p->ext_flags & NEXTERN) == 0)) 892 nerror("Unresolved forward declaration of %s %s", classes[p->class], p->symbol); 893 # endif PC 894 break; 895 896 case LABEL: 897 if (p->nl_flags & NFORWD) 898 nerror("label %s was declared but not defined", p->symbol); 899 break; 900 case FVAR: 901 if ((p->nl_flags & NMOD) == 0) 902 nerror("No assignment to the function variable"); 903 break; 904 } 905 } 906 /* 907 * Pop this symbol 908 * table slot 909 */ 910 disptab[i] = p; 911 } 912 913 # ifdef OBJ 914 put(1, O_END); 915 # endif OBJ 916 # ifdef PC 917 /* 918 * if there were file variables declared at this level 919 * call pclose( &__disply[ cbn ] ) to clean them up. 920 */ 921 if ( dfiles[ cbn ] ) { 922 putleaf( P2ICON , 0 , 0 , ADDTYPE( P2FTN | P2INT , P2PTR ) 923 , "_PCLOSE" ); 924 putRV( DISPLAYNAME , 0 , cbn * sizeof( struct dispsave ) 925 , P2PTR | P2CHAR ); 926 putop( P2CALL , P2INT ); 927 putdot( filename , line ); 928 } 929 /* 930 * if this is a function, 931 * the function variable is the return value. 932 * if it's a scalar valued function, return scalar, 933 * else, return a pointer to the structure value. 934 */ 935 if ( fp -> class == FUNC ) { 936 struct nl *fvar = fp -> ptr[ NL_FVAR ]; 937 long fvartype = p2type( fvar -> type ); 938 long label; 939 char labelname[ BUFSIZ ]; 940 941 switch ( classify( fvar -> type ) ) { 942 case TBOOL: 943 case TCHAR: 944 case TINT: 945 case TSCAL: 946 case TDOUBLE: 947 case TPTR: 948 putRV( fvar -> symbol , ( fvar -> nl_block ) & 037 949 , fvar -> value[ NL_OFFS ] , fvartype ); 950 break; 951 default: 952 label = getlab(); 953 sprintf( labelname , PREFIXFORMAT , 954 LABELPREFIX , label ); 955 putprintf( " .data" , 0 ); 956 putprintf( " .lcomm %s,%d" , 0 , 957 labelname , lwidth( fvar -> type ) ); 958 putprintf( " .text" , 0 ); 959 putleaf( P2NAME , 0 , 0 , fvartype , labelname ); 960 putLV( fvar -> symbol , ( fvar -> nl_block ) & 037 961 , fvar -> value[ NL_OFFS ] , fvartype ); 962 putstrop( P2STASG , fvartype , lwidth( fvar -> type ) , 963 align( fvar -> type ) ); 964 putdot( filename , line ); 965 putleaf( P2ICON , 0 , 0 , fvartype , labelname ); 966 break; 967 } 968 putop( P2FORCE , fvartype ); 969 putdot( filename , line ); 970 } 971 /* 972 * restore old display entry from save area 973 */ 974 975 putprintf( " movq %d(%s),%s+%d" , 0 976 , DSAVEOFFSET , P2FPNAME 977 , DISPLAYNAME , cbn * sizeof(struct dispsave) ); 978 stabrbrac( cbn ); 979 putprintf( " ret" , 0 ); 980 /* 981 * let the second pass allocate locals 982 */ 983 putlab( botlabel ); 984 putprintf( " subl2 $LF%d,sp" , 0 , ftnno ); 985 putrbracket( ftnno ); 986 putjbr( toplabel ); 987 /* 988 * declare pcp counters, if any 989 */ 990 if ( monflg && fp -> class == PROG ) { 991 putprintf( " .data" , 0 ); 992 putprintf( " .comm " , 1 ); 993 putprintf( PCPCOUNT , 1 ); 994 putprintf( ",%d" , 0 , ( cnts + 1 ) * sizeof (long) ); 995 putprintf( " .text" , 0 ); 996 } 997 # endif PC 998 #ifdef DEBUG 999 dumpnl(fp->ptr[2], fp->symbol); 1000 #endif 1001 /* 1002 * Restore the 1003 * (virtual) name list 1004 * position 1005 */ 1006 nlfree(fp->ptr[2]); 1007 /* 1008 * Proc/func has been 1009 * resolved 1010 */ 1011 fp->nl_flags &= ~NFORWD; 1012 /* 1013 * Patch the beg 1014 * of the proc/func to 1015 * the proper variable size 1016 */ 1017 if (Fp == NIL) 1018 elineon(); 1019 # ifdef OBJ 1020 patchfil(var, -sizes[cbn].om_max, 2); 1021 # endif OBJ 1022 cbn--; 1023 if (inpflist(fp->symbol)) { 1024 opop('l'); 1025 } 1026 } 1027 1028 1029 /* 1030 * Segend is called to check for 1031 * unresolved variables, funcs and 1032 * procs, and deliver unresolved and 1033 * baduse error diagnostics at the 1034 * end of a routine segment (a separately 1035 * compiled segment that is not the 1036 * main program) for PC. This 1037 * routine should only be called 1038 * by PC (not standard). 1039 */ 1040 segend() 1041 { 1042 register struct nl *p; 1043 register int i,b; 1044 char *cp; 1045 1046 #ifdef PC 1047 if (opt('s')) { 1048 standard(); 1049 error("Separately compiled routine segments are not standard."); 1050 } else { 1051 b = cbn; 1052 for (i=0; i<077; i++) { 1053 for (p = disptab[i]; p != NIL && (p->nl_block & 037) == b; p = p->nl_next) { 1054 switch (p->class) { 1055 case BADUSE: 1056 cp = 's'; 1057 if (p->chain->ud_next == NIL) 1058 cp++; 1059 eholdnl(); 1060 if (p->value[NL_KINDS] & ISUNDEF) 1061 nerror("%s undefined on line%s", p->symbol, cp); 1062 else 1063 nerror("%s improperly used on line%s", p->symbol, cp); 1064 pnumcnt = 10; 1065 pnums(p->chain); 1066 pchr('\n'); 1067 break; 1068 1069 case FUNC: 1070 case PROC: 1071 if ((p->nl_flags & NFORWD) && ((p->ext_flags & NEXTERN) == 0)) 1072 nerror("Unresolved forward declaration of %s %s", classes[p->class], p->symbol); 1073 break; 1074 1075 case FVAR: 1076 if (((p->nl_flags & NMOD) == 0) && ((p->chain->ext_flags & NEXTERN) == 0)) 1077 nerror("No assignment to the function variable"); 1078 break; 1079 } 1080 } 1081 disptab[i] = p; 1082 } 1083 } 1084 #endif PC 1085 #ifdef OBJ 1086 error("Missing program statement and program body"); 1087 #endif OBJ 1088 1089 } 1090 1091 1092 /* 1093 * Level1 does level one processing for 1094 * separately compiled routine segments 1095 */ 1096 level1() 1097 { 1098 1099 # ifdef OBJ 1100 error("Missing program statement"); 1101 # endif OBJ 1102 # ifdef PC 1103 if (opt('s')) { 1104 standard(); 1105 error("Missing program statement"); 1106 } 1107 # endif PC 1108 1109 cbn++; 1110 sizes[cbn].om_max = sizes[cbn].om_off = -DPOFF1; 1111 gotos[cbn] = NIL; 1112 errcnt[cbn] = syneflg; 1113 parts[ cbn ] = NIL; 1114 dfiles[ cbn ] = FALSE; 1115 progseen++; 1116 } 1117 1118 1119 1120 pnums(p) 1121 struct udinfo *p; 1122 { 1123 1124 if (p->ud_next != NIL) 1125 pnums(p->ud_next); 1126 if (pnumcnt == 0) { 1127 printf("\n\t"); 1128 pnumcnt = 20; 1129 } 1130 pnumcnt--; 1131 printf(" %d", p->ud_line); 1132 } 1133 1134 nerror(a1, a2, a3) 1135 { 1136 1137 if (Fp != NIL) { 1138 yySsync(); 1139 #ifndef PI1 1140 if (opt('l')) 1141 yyoutline(); 1142 #endif 1143 yysetfile(filename); 1144 printf("In %s %s:\n", classes[Fp->class], Fp->symbol); 1145 Fp = NIL; 1146 elineoff(); 1147 } 1148 error(a1, a2, a3); 1149 } 1150