1752Speter /* Copyright (c) 1979 Regents of the University of California */ 2752Speter 3*2220Smckusic static char sccsid[] = "@(#)fdec.c 1.13 01/24/81"; 4752Speter 5752Speter #include "whoami.h" 6752Speter #include "0.h" 7752Speter #include "tree.h" 8752Speter #include "opcode.h" 9752Speter #include "objfmt.h" 10752Speter #include "align.h" 11752Speter 12752Speter /* 13752Speter * this array keeps the pxp counters associated with 14752Speter * functions and procedures, so that they can be output 15752Speter * when their bodies are encountered 16752Speter */ 17752Speter int bodycnts[ DSPLYSZ ]; 18752Speter 19752Speter #ifdef PC 20752Speter # include "pc.h" 21752Speter # include "pcops.h" 22752Speter #endif PC 23752Speter 24752Speter #ifdef OBJ 25752Speter int cntpatch; 26752Speter int nfppatch; 27752Speter #endif OBJ 28752Speter 29752Speter /* 30752Speter * Funchdr inserts 31752Speter * declaration of a the 32752Speter * prog/proc/func into the 33752Speter * namelist. It also handles 34752Speter * the arguments and puts out 35752Speter * a transfer which defines 36752Speter * the entry point of a procedure. 37752Speter */ 38752Speter 39752Speter struct nl * 40752Speter funchdr(r) 41752Speter int *r; 42752Speter { 43752Speter register struct nl *p; 44752Speter register *il, **rl; 45752Speter int *rll; 46752Speter struct nl *cp, *dp, *sp; 47752Speter int s, o, *pp; 48752Speter 49752Speter if (inpflist(r[2])) { 50752Speter opush('l'); 51752Speter yyretrieve(); /* kludge */ 52752Speter } 53752Speter pfcnt++; 54834Speter parts[ cbn ] |= RPRT; 55752Speter line = r[1]; 56752Speter if (r[3] == NIL && (p=lookup1(r[2])) != NIL && bn == cbn) { 57752Speter /* 58752Speter * Symbol already defined 59752Speter * in this block. it is either 60752Speter * a redeclared symbol (error) 61752Speter * a forward declaration, 62752Speter * or an external declaration. 63752Speter */ 64752Speter if ((p->class == FUNC || p->class == PROC) && (p->nl_flags & NFORWD) != 0) { 65752Speter /* 66752Speter * Grammar doesnt forbid 67752Speter * types on a resolution 68752Speter * of a forward function 69752Speter * declaration. 70752Speter */ 71752Speter if (p->class == FUNC && r[4]) 72752Speter error("Function type should be given only in forward declaration"); 73752Speter /* 74752Speter * get another counter for the actual 75752Speter */ 76752Speter if ( monflg ) { 77752Speter bodycnts[ cbn ] = getcnt(); 78752Speter } 79752Speter # ifdef PC 80752Speter enclosing[ cbn ] = p -> symbol; 81752Speter # endif PC 82752Speter # ifdef PTREE 83752Speter /* 84752Speter * mark this proc/func as forward 85752Speter * in the pTree. 86752Speter */ 87752Speter pDEF( p -> inTree ).PorFForward = TRUE; 88752Speter # endif PTREE 89752Speter return (p); 90752Speter } 91752Speter } 92752Speter 93752Speter /* if a routine segment is being compiled, 94752Speter * do level one processing. 95752Speter */ 96752Speter 97752Speter if ((r[0] != T_PROG) && (!progseen)) 98752Speter level1(); 99752Speter 100752Speter 101752Speter /* 102752Speter * Declare the prog/proc/func 103752Speter */ 104752Speter switch (r[0]) { 105752Speter case T_PROG: 106752Speter progseen++; 107752Speter if (opt('z')) 108752Speter monflg++; 109752Speter program = p = defnl(r[2], PROG, 0, 0); 110752Speter p->value[3] = r[1]; 111752Speter break; 112752Speter case T_PDEC: 113752Speter if (r[4] != NIL) 114752Speter error("Procedures do not have types, only functions do"); 115752Speter p = enter(defnl(r[2], PROC, 0, 0)); 116752Speter p->nl_flags |= NMOD; 117752Speter # ifdef PC 118752Speter enclosing[ cbn ] = r[2]; 119752Speter # endif PC 120752Speter break; 121752Speter case T_FDEC: 122752Speter il = r[4]; 123752Speter if (il == NIL) 124752Speter error("Function type must be specified"); 125752Speter else if (il[0] != T_TYID) { 126752Speter il = NIL; 127752Speter error("Function type can be specified only by using a type identifier"); 128752Speter } else 129752Speter il = gtype(il); 130752Speter p = enter(defnl(r[2], FUNC, il, NIL)); 131752Speter p->nl_flags |= NMOD; 132752Speter /* 133752Speter * An arbitrary restriction 134752Speter */ 135752Speter switch (o = classify(p->type)) { 136752Speter case TFILE: 137752Speter case TARY: 138752Speter case TREC: 139752Speter case TSET: 140752Speter case TSTR: 1411626Speter warning(); 1421196Speter if (opt('s')) { 143752Speter standard(); 1441196Speter } 1451626Speter error("Functions should not return %ss", clnames[o]); 146752Speter } 147752Speter # ifdef PC 148752Speter enclosing[ cbn ] = r[2]; 149752Speter # endif PC 150752Speter break; 151752Speter default: 152752Speter panic("funchdr"); 153752Speter } 154752Speter if (r[0] != T_PROG) { 155752Speter /* 156752Speter * Mark this proc/func as 157752Speter * being forward declared 158752Speter */ 159752Speter p->nl_flags |= NFORWD; 160752Speter /* 161752Speter * Enter the parameters 162752Speter * in the next block for 163752Speter * the time being 164752Speter */ 165752Speter if (++cbn >= DSPLYSZ) { 166752Speter error("Procedure/function nesting too deep"); 167752Speter pexit(ERRS); 168752Speter } 169752Speter /* 170752Speter * For functions, the function variable 171752Speter */ 172752Speter if (p->class == FUNC) { 173752Speter # ifdef OBJ 174752Speter cp = defnl(r[2], FVAR, p->type, 0); 175752Speter # endif OBJ 176752Speter # ifdef PC 177752Speter /* 178752Speter * fvars used to be allocated and deallocated 179752Speter * by the caller right before the arguments. 180752Speter * the offset of the fvar was kept in 181752Speter * value[NL_OFFS] of function (very wierd, 182752Speter * but see asgnop). 183752Speter * now, they are locals to the function 184752Speter * with the offset kept in the fvar. 185752Speter */ 186752Speter 187752Speter cp = defnl( r[2] , FVAR , p -> type 188752Speter , -( roundup( DPOFF1+width( p -> type ) 189752Speter , align( p -> type ) ) ) ); 190752Speter # endif PC 191752Speter cp->chain = p; 192752Speter p->ptr[NL_FVAR] = cp; 193752Speter } 194752Speter /* 195752Speter * Enter the parameters 196752Speter * and compute total size 197752Speter */ 198752Speter cp = sp = p; 199752Speter 200752Speter # ifdef OBJ 201752Speter o = 0; 202752Speter # endif OBJ 203752Speter # ifdef PC 204752Speter /* 205752Speter * parameters used to be allocated backwards, 206752Speter * then fixed. for pc, they are allocated correctly. 207752Speter * also, they are aligned. 208752Speter */ 209752Speter o = DPOFF2; 210752Speter # endif PC 211752Speter for (rl = r[3]; rl != NIL; rl = rl[2]) { 212752Speter p = NIL; 213752Speter if (rl[1] == NIL) 214752Speter continue; 215752Speter /* 216752Speter * Parametric procedures 217752Speter * don't have types !?! 218752Speter */ 219752Speter if (rl[1][0] != T_PPROC) { 220752Speter rll = rl[1][2]; 221752Speter if (rll[0] != T_TYID) { 222752Speter error("Types for arguments can be specified only by using type identifiers"); 223752Speter p = NIL; 224752Speter } else 225752Speter p = gtype(rll); 226752Speter } 227752Speter for (il = rl[1][1]; il != NIL; il = il[2]) { 228752Speter switch (rl[1][0]) { 229752Speter default: 230752Speter panic("funchdr2"); 231752Speter case T_PVAL: 232752Speter if (p != NIL) { 233752Speter if (p->class == FILET) 234752Speter error("Files cannot be passed by value"); 235752Speter else if (p->nl_flags & NFILES) 236752Speter error("Files cannot be a component of %ss passed by value", 237752Speter nameof(p)); 238752Speter } 239752Speter # ifdef OBJ 240752Speter dp = defnl(il[1], VAR, p, o -= even(width(p))); 241752Speter # endif OBJ 242752Speter # ifdef PC 243752Speter dp = defnl( il[1] , VAR , p 244752Speter , o = roundup( o , A_STACK ) ); 245752Speter o += width( p ); 246752Speter # endif PC 247752Speter dp->nl_flags |= NMOD; 248752Speter break; 249752Speter case T_PVAR: 250752Speter # ifdef OBJ 251752Speter dp = defnl(il[1], REF, p, o -= sizeof ( int * ) ); 252752Speter # endif OBJ 253752Speter # ifdef PC 254752Speter dp = defnl( il[1] , REF , p 255752Speter , o = roundup( o , A_STACK ) ); 256752Speter o += sizeof(char *); 257752Speter # endif PC 258752Speter break; 259752Speter case T_PFUNC: 2601196Speter # ifdef OBJ 2611196Speter dp = defnl(il[1], FFUNC, p, o -= sizeof ( int * ) ); 2621196Speter # endif OBJ 2631196Speter # ifdef PC 2641196Speter dp = defnl( il[1] , FFUNC , p 2651196Speter , o = roundup( o , A_STACK ) ); 2661196Speter o += sizeof(char *); 2671196Speter # endif PC 2681196Speter dp -> nl_flags |= NMOD; 2691196Speter break; 270752Speter case T_PPROC: 2711196Speter # ifdef OBJ 2721196Speter dp = defnl(il[1], FPROC, p, o -= sizeof ( int * ) ); 2731196Speter # endif OBJ 2741196Speter # ifdef PC 2751196Speter dp = defnl( il[1] , FPROC , p 2761196Speter , o = roundup( o , A_STACK ) ); 2771196Speter o += sizeof(char *); 2781196Speter # endif PC 2791196Speter dp -> nl_flags |= NMOD; 2801196Speter break; 281752Speter } 282752Speter if (dp != NIL) { 283752Speter cp->chain = dp; 284752Speter cp = dp; 285752Speter } 286752Speter } 287752Speter } 288752Speter cbn--; 289752Speter p = sp; 290752Speter # ifdef OBJ 291752Speter p->value[NL_OFFS] = -o+DPOFF2; 292752Speter /* 293752Speter * Correct the naivete (naievity) 294752Speter * of our above code to 295752Speter * calculate offsets 296752Speter */ 297752Speter for (il = p->chain; il != NIL; il = il->chain) 298752Speter il->value[NL_OFFS] += p->value[NL_OFFS]; 299752Speter # endif OBJ 300752Speter # ifdef PC 3011620Speter p -> value[ NL_OFFS ] = roundup( o , A_STACK ); 302752Speter # endif PC 303752Speter } else { 304752Speter /* 305752Speter * The wonderful 306752Speter * program statement! 307752Speter */ 308752Speter # ifdef OBJ 309752Speter if (monflg) { 310752Speter put(1, O_PXPBUF); 311752Speter cntpatch = put(2, O_CASE4, 0); 312752Speter nfppatch = put(2, O_CASE4, 0); 313752Speter } 314752Speter # endif OBJ 315752Speter cp = p; 316752Speter for (rl = r[3]; rl; rl = rl[2]) { 317752Speter if (rl[1] == NIL) 318752Speter continue; 319752Speter dp = defnl(rl[1], VAR, 0, 0); 320752Speter cp->chain = dp; 321752Speter cp = dp; 322752Speter } 323752Speter } 324752Speter /* 325752Speter * Define a branch at 326752Speter * the "entry point" of 327752Speter * the prog/proc/func. 328752Speter */ 329752Speter p->entloc = getlab(); 330752Speter if (monflg) { 331752Speter bodycnts[ cbn ] = getcnt(); 332752Speter p->value[ NL_CNTR ] = 0; 333752Speter } 334752Speter # ifdef OBJ 335752Speter put(2, O_TRA4, p->entloc); 336752Speter # endif OBJ 337752Speter # ifdef PTREE 338752Speter { 339752Speter pPointer PF = tCopy( r ); 340752Speter 341752Speter pSeize( PorFHeader[ nesting ] ); 342752Speter if ( r[0] != T_PROG ) { 343752Speter pPointer *PFs; 344752Speter 345752Speter PFs = &( pDEF( PorFHeader[ nesting ] ).PorFPFs ); 346752Speter *PFs = ListAppend( *PFs , PF ); 347752Speter } else { 348752Speter pDEF( PorFHeader[ nesting ] ).GlobProg = PF; 349752Speter } 350752Speter pRelease( PorFHeader[ nesting ] ); 351752Speter } 352752Speter # endif PTREE 353752Speter return (p); 354752Speter } 355752Speter 356752Speter funcfwd(fp) 357752Speter struct nl *fp; 358752Speter { 359752Speter 360752Speter /* 361752Speter * save the counter for this function 362752Speter */ 363752Speter if ( monflg ) { 364752Speter fp -> value[ NL_CNTR ] = bodycnts[ cbn ]; 365752Speter } 366752Speter return (fp); 367752Speter } 368752Speter 369752Speter /* 370752Speter * Funcext marks the procedure or 371752Speter * function external in the symbol 372752Speter * table. Funcext should only be 373752Speter * called if PC, and is an error 374752Speter * otherwise. 375752Speter */ 376752Speter 377752Speter funcext(fp) 378752Speter struct nl *fp; 379752Speter { 380752Speter 381752Speter #ifdef PC 382752Speter if (opt('s')) { 383752Speter standard(); 384752Speter error("External procedures and functions are not standard"); 385752Speter } else { 386752Speter if (cbn == 1) { 387752Speter fp->ext_flags |= NEXTERN; 388825Speter stabefunc( fp -> symbol , fp -> class , line ); 389752Speter } 390752Speter else 391752Speter error("External procedures and functions can only be declared at the outermost level."); 392752Speter } 393752Speter #endif PC 394752Speter #ifdef OBJ 395752Speter error("Procedures or functions cannot be declared external."); 396752Speter #endif OBJ 397752Speter 398752Speter return(fp); 399752Speter } 400752Speter 401752Speter /* 402752Speter * Funcbody is called 403752Speter * when the actual (resolved) 404752Speter * declaration of a procedure is 405752Speter * encountered. It puts the names 406752Speter * of the (function) and parameters 407752Speter * into the symbol table. 408752Speter */ 409752Speter funcbody(fp) 410752Speter struct nl *fp; 411752Speter { 412752Speter register struct nl *q, *p; 413752Speter 414752Speter cbn++; 415752Speter if (cbn >= DSPLYSZ) { 416752Speter error("Too many levels of function/procedure nesting"); 417752Speter pexit(ERRS); 418752Speter } 419752Speter sizes[cbn].om_max = sizes[cbn].om_off = -DPOFF1; 420752Speter gotos[cbn] = NIL; 421752Speter errcnt[cbn] = syneflg; 422834Speter parts[ cbn ] = NIL; 423752Speter dfiles[ cbn ] = FALSE; 424752Speter if (fp == NIL) 425752Speter return (NIL); 426752Speter /* 427752Speter * Save the virtual name 428752Speter * list stack pointer so 429752Speter * the space can be freed 430752Speter * later (funcend). 431752Speter */ 432752Speter fp->ptr[2] = nlp; 433752Speter if (fp->class != PROG) { 434752Speter for (q = fp->chain; q != NIL; q = q->chain) { 435752Speter enter(q); 436752Speter } 437752Speter } 438752Speter if (fp->class == FUNC) { 439752Speter /* 440752Speter * For functions, enter the fvar 441752Speter */ 442752Speter enter(fp->ptr[NL_FVAR]); 443752Speter # ifdef PC 444752Speter q = fp -> ptr[ NL_FVAR ]; 445752Speter sizes[cbn].om_off -= lwidth( q -> type ); 446752Speter sizes[cbn].om_max = sizes[cbn].om_off; 447752Speter # endif PC 448752Speter } 449752Speter # ifdef PTREE 450752Speter /* 451752Speter * pick up the pointer to porf declaration 452752Speter */ 453752Speter PorFHeader[ ++nesting ] = fp -> inTree; 454752Speter # endif PTREE 455752Speter return (fp); 456752Speter } 457752Speter 458752Speter struct nl *Fp; 459752Speter int pnumcnt; 460752Speter /* 461752Speter * Funcend is called to 462752Speter * finish a block by generating 463752Speter * the code for the statements. 464752Speter * It then looks for unresolved declarations 465752Speter * of labels, procedures and functions, 466752Speter * and cleans up the name list. 467752Speter * For the program, it checks the 468752Speter * semantics of the program 469752Speter * statement (yuchh). 470752Speter */ 471752Speter funcend(fp, bundle, endline) 472752Speter struct nl *fp; 473752Speter int *bundle; 474752Speter int endline; 475752Speter { 476752Speter register struct nl *p; 477752Speter register int i, b; 478752Speter int var, inp, out, chkref, *blk; 479752Speter struct nl *iop; 480752Speter char *cp; 481752Speter extern int cntstat; 482752Speter # ifdef PC 483752Speter int toplabel = getlab(); 484752Speter int botlabel = getlab(); 485752Speter # endif PC 486752Speter 487752Speter cntstat = 0; 488752Speter /* 489752Speter * yyoutline(); 490752Speter */ 491752Speter if (program != NIL) 492752Speter line = program->value[3]; 493752Speter blk = bundle[2]; 494752Speter if (fp == NIL) { 495752Speter cbn--; 496752Speter # ifdef PTREE 497752Speter nesting--; 498752Speter # endif PTREE 499752Speter return; 500752Speter } 501752Speter #ifdef OBJ 502752Speter /* 503752Speter * Patch the branch to the 504752Speter * entry point of the function 505752Speter */ 506752Speter patch4(fp->entloc); 507752Speter /* 508752Speter * Put out the block entrance code and the block name. 509*2220Smckusic * HDRSZE is the number of bytes of info in the static 510*2220Smckusic * BEG data area exclusive of the proc name. It is 511*2220Smckusic * currently defined as: 512*2220Smckusic /* struct hdr { 513*2220Smckusic /* long framesze; /* number of bytes of local vars */ 514*2220Smckusic /* long nargs; /* number of bytes of arguments */ 515*2220Smckusic /* short tests; /* TRUE => perform runtime tests */ 516*2220Smckusic /* short offset; /* offset of procedure in source file */ 517*2220Smckusic /* char name[1]; /* name of active procedure */ 518*2220Smckusic /* }; 519752Speter */ 520*2220Smckusic # define HDRSZE 12 521*2220Smckusic var = put(2, (lenstr(fp->symbol,0) + HDRSZE << 8) 522752Speter | (cbn == 1 && opt('p') == 0 ? O_NODUMP: O_BEG), 0); 5231196Speter /* 5241196Speter * output the number of bytes of arguments 5251196Speter * this is only checked on formal calls. 5261196Speter */ 5271196Speter put(2, O_CASE4, cbn == 1 ? 0 : fp->value[NL_OFFS]-DPOFF2); 5282190Smckusic /* 5292190Smckusic * Output the runtime test mode for the routine 5302190Smckusic */ 5312190Smckusic if (opt('t')) 5322190Smckusic put(2, O_CASE2, TRUE); 5332190Smckusic else 5342190Smckusic put(2, O_CASE2, FALSE); 5352190Smckusic /* 5362190Smckusic * Output line number and routine name 5372190Smckusic */ 538752Speter put(2, O_CASE2, bundle[1]); 539752Speter putstr(fp->symbol, 0); 540752Speter #endif OBJ 541752Speter #ifdef PC 542752Speter /* 543752Speter * put out the procedure entry code 544752Speter */ 545752Speter if ( fp -> class == PROG ) { 546752Speter putprintf( " .text" , 0 ); 547752Speter putprintf( " .align 1" , 0 ); 548752Speter putprintf( " .globl _main" , 0 ); 549752Speter putprintf( "_main:" , 0 ); 550752Speter putprintf( " .word 0" , 0 ); 551752Speter putprintf( " calls $0,_PCSTART" , 0 ); 552752Speter putprintf( " movl 4(ap),__argc" , 0 ); 553752Speter putprintf( " movl 8(ap),__argv" , 0 ); 554752Speter putprintf( " calls $0,_program" , 0 ); 555752Speter putprintf( " calls $0,_PCEXIT" , 0 ); 556752Speter ftnno = fp -> entloc; 557752Speter putprintf( " .text" , 0 ); 558752Speter putprintf( " .align 1" , 0 ); 559752Speter putprintf( " .globl _program" , 0 ); 560752Speter putprintf( "_program:" , 0 ); 5612163Speter stabfunc( "program" , fp -> class , bundle[1] , 0 ); 562752Speter } else { 563752Speter ftnno = fp -> entloc; 564752Speter putprintf( " .text" , 0 ); 565752Speter putprintf( " .align 1" , 0 ); 566752Speter putprintf( " .globl " , 1 ); 567752Speter for ( i = 1 ; i < cbn ; i++ ) { 568752Speter putprintf( EXTFORMAT , 1 , enclosing[ i ] ); 569752Speter } 570752Speter putprintf( "" , 0 ); 571752Speter for ( i = 1 ; i < cbn ; i++ ) { 572752Speter putprintf( EXTFORMAT , 1 , enclosing[ i ] ); 573752Speter } 574752Speter putprintf( ":" , 0 ); 5752163Speter stabfunc( fp -> symbol , fp -> class , bundle[1] , cbn - 1 ); 5762163Speter for ( p = fp -> chain ; p != NIL ; p = p -> chain ) { 5772163Speter stabparam( p -> symbol , p2type( p -> type ) 5782163Speter , p -> value[ NL_OFFS ] , lwidth( p -> type ) ); 5792163Speter } 5802163Speter if ( fp -> class == FUNC ) { 5812163Speter /* 5822163Speter * stab the function variable 5832163Speter */ 5842163Speter p = fp -> ptr[ NL_FVAR ]; 5852163Speter stablvar( p -> symbol , p2type( p -> type ) , cbn 5862163Speter , p -> value[ NL_OFFS ] , lwidth( p -> type ) ); 5872163Speter } 5882163Speter /* 5892163Speter * stab local variables 5902163Speter * rummage down hash chain links. 5912163Speter */ 5922163Speter for ( i = 0 ; i <= 077 ; i++ ) { 5932163Speter for ( p = disptab[ i ] ; p != NIL ; p = p->nl_next) { 5942163Speter if ( ( p -> nl_block & 037 ) != cbn ) { 5952163Speter break; 5962163Speter } 5972163Speter /* 5982163Speter * stab local variables 5992163Speter * that's named variables, but not params 6002163Speter */ 6012163Speter if ( ( p -> symbol != NIL ) 6022163Speter && ( p -> class == VAR ) 6032163Speter && ( p -> value[ NL_OFFS ] < 0 ) ) { 6042163Speter stablvar( p -> symbol , p2type( p -> type ) , cbn 6052163Speter , p -> value[ NL_OFFS ] , lwidth( p -> type ) ); 6062163Speter } 6072163Speter } 6082163Speter } 609752Speter } 610752Speter stablbrac( cbn ); 611752Speter /* 612752Speter * register save mask 613752Speter */ 614752Speter if ( opt( 't' ) ) { 615752Speter putprintf( " .word 0x%x" , 0 , RUNCHECK | RSAVEMASK ); 616752Speter } else { 617752Speter putprintf( " .word 0x%x" , 0 , RSAVEMASK ); 618752Speter } 619752Speter putjbr( botlabel ); 620752Speter putlab( toplabel ); 621752Speter if ( profflag ) { 622752Speter /* 623752Speter * call mcount for profiling 624752Speter */ 625752Speter putprintf( " moval 1f,r0" , 0 ); 626752Speter putprintf( " jsb mcount" , 0 ); 627752Speter putprintf( " .data" , 0 ); 628752Speter putprintf( " .align 2" , 0 ); 629752Speter putprintf( "1:" , 0 ); 630752Speter putprintf( " .long 0" , 0 ); 631752Speter putprintf( " .text" , 0 ); 632752Speter } 633752Speter /* 634752Speter * set up unwind exception vector. 635752Speter */ 636752Speter putprintf( " moval %s,%d(%s)" , 0 637752Speter , UNWINDNAME , UNWINDOFFSET , P2FPNAME ); 638752Speter /* 639752Speter * save address of display entry, for unwind. 640752Speter */ 641752Speter putprintf( " moval %s+%d,%d(%s)" , 0 642752Speter , DISPLAYNAME , cbn * sizeof(struct dispsave) 643752Speter , DPTROFFSET , P2FPNAME ); 644752Speter /* 645752Speter * save old display 646752Speter */ 647752Speter putprintf( " movq %s+%d,%d(%s)" , 0 648752Speter , DISPLAYNAME , cbn * sizeof(struct dispsave) 649752Speter , DSAVEOFFSET , P2FPNAME ); 650752Speter /* 651752Speter * set up new display by saving AP and FP in appropriate 652752Speter * slot in display structure. 653752Speter */ 654752Speter putprintf( " movq %s,%s+%d" , 0 655752Speter , P2APNAME , DISPLAYNAME , cbn * sizeof(struct dispsave) ); 656752Speter /* 657752Speter * ask second pass to allocate known locals 658752Speter */ 659752Speter putlbracket( ftnno , -sizes[ cbn ].om_max ); 660752Speter /* 661752Speter * and zero them if checking is on 6622125Smckusic * by calling blkclr( bytes of locals , starting local address ); 663752Speter */ 6641196Speter if ( opt( 't' ) ) { 6651196Speter if ( ( -sizes[ cbn ].om_max ) > DPOFF1 ) { 6661196Speter putleaf( P2ICON , 0 , 0 , ADDTYPE( P2FTN | P2INT , P2PTR ) 6672125Smckusic , "_blkclr" ); 6681196Speter putleaf( P2ICON , ( -sizes[ cbn ].om_max ) - DPOFF1 6691196Speter , 0 , P2INT , 0 ); 6701196Speter putLV( 0 , cbn , sizes[ cbn ].om_max , P2CHAR ); 6711196Speter putop( P2LISTOP , P2INT ); 6721196Speter putop( P2CALL , P2INT ); 6731196Speter putdot( filename , line ); 6741196Speter } 6751196Speter /* 6761196Speter * check number of longs of arguments 6771196Speter * this can only be wrong for formal calls. 6781196Speter */ 6791196Speter if ( fp -> class != PROG ) { 6801196Speter putleaf( P2ICON , 0 , 0 , ADDTYPE( P2PTR , P2FTN | P2INT ) , 6811196Speter "_NARGCHK" ); 6821196Speter putleaf( P2ICON , 6831196Speter (fp->value[NL_OFFS] - DPOFF2) / sizeof(long) , 6841196Speter 0 , P2INT , 0 ); 6851196Speter putop( P2CALL , P2INT ); 6861196Speter putdot( filename , line ); 6871196Speter } 688752Speter } 689752Speter #endif PC 690752Speter if ( monflg ) { 691752Speter if ( fp -> value[ NL_CNTR ] != 0 ) { 692752Speter inccnt( fp -> value [ NL_CNTR ] ); 693752Speter } 694752Speter inccnt( bodycnts[ fp -> nl_block & 037 ] ); 695752Speter } 696752Speter if (fp->class == PROG) { 697752Speter /* 698752Speter * The glorious buffers option. 699752Speter * 0 = don't buffer output 700752Speter * 1 = line buffer output 701752Speter * 2 = 512 byte buffer output 702752Speter */ 703752Speter # ifdef OBJ 704752Speter if (opt('b') != 1) 705752Speter put(1, O_BUFF | opt('b') << 8); 706752Speter # endif OBJ 707752Speter # ifdef PC 708752Speter if ( opt( 'b' ) != 1 ) { 709752Speter putleaf( P2ICON , 0 , 0 710752Speter , ADDTYPE( P2FTN | P2INT , P2PTR ) , "_BUFF" ); 711752Speter putleaf( P2ICON , opt( 'b' ) , 0 , P2INT , 0 ); 712752Speter putop( P2CALL , P2INT ); 713752Speter putdot( filename , line ); 714752Speter } 715752Speter # endif PC 716752Speter out = 0; 717752Speter for (p = fp->chain; p != NIL; p = p->chain) { 718752Speter if (strcmp(p->symbol, "input") == 0) { 719752Speter inp++; 720752Speter continue; 721752Speter } 722752Speter if (strcmp(p->symbol, "output") == 0) { 723752Speter out++; 724752Speter continue; 725752Speter } 726752Speter iop = lookup1(p->symbol); 727752Speter if (iop == NIL || bn != cbn) { 728752Speter error("File %s listed in program statement but not declared", p->symbol); 729752Speter continue; 730752Speter } 731752Speter if (iop->class != VAR) { 732752Speter error("File %s listed in program statement but declared as a %s", p->symbol, classes[iop->class]); 733752Speter continue; 734752Speter } 735752Speter if (iop->type == NIL) 736752Speter continue; 737752Speter if (iop->type->class != FILET) { 738752Speter error("File %s listed in program statement but defined as %s", 739752Speter p->symbol, nameof(iop->type)); 740752Speter continue; 741752Speter } 742752Speter # ifdef OBJ 7432068Smckusic put(2, O_CON24, text(iop->type) ? 0 : width(iop->type->type)); 744752Speter i = lenstr(p->symbol,0); 7452068Smckusic put(2, O_CON24, i); 746752Speter put(2, O_LVCON, i); 747752Speter putstr(p->symbol, 0); 7482068Smckusic put(2, O_LV | bn << 8+INDX, iop->value[NL_OFFS]); 749752Speter put(1, O_DEFNAME); 750752Speter # endif OBJ 751752Speter # ifdef PC 752752Speter putleaf( P2ICON , 0 , 0 753752Speter , ADDTYPE( P2FTN | P2INT , P2PTR ) 754752Speter , "_DEFNAME" ); 755752Speter putLV( p -> symbol , bn , iop -> value[NL_OFFS] 756752Speter , p2type( iop ) ); 757752Speter putCONG( p -> symbol , strlen( p -> symbol ) 758752Speter , LREQ ); 759752Speter putop( P2LISTOP , P2INT ); 760752Speter putleaf( P2ICON , strlen( p -> symbol ) 761752Speter , 0 , P2INT , 0 ); 762752Speter putop( P2LISTOP , P2INT ); 763752Speter putleaf( P2ICON 764752Speter , text(iop->type) ? 0 : width(iop->type->type) 765752Speter , 0 , P2INT , 0 ); 766752Speter putop( P2LISTOP , P2INT ); 767752Speter putop( P2CALL , P2INT ); 768752Speter putdot( filename , line ); 769752Speter # endif PC 770752Speter } 771752Speter if (out == 0 && fp->chain != NIL) { 772752Speter recovered(); 773752Speter error("The file output must appear in the program statement file list"); 774752Speter } 775752Speter } 776752Speter /* 777752Speter * Process the prog/proc/func body 778752Speter */ 779752Speter noreach = 0; 780752Speter line = bundle[1]; 781752Speter statlist(blk); 782752Speter # ifdef PTREE 783752Speter { 784752Speter pPointer Body = tCopy( blk ); 785752Speter 786752Speter pDEF( PorFHeader[ nesting -- ] ).PorFBody = Body; 787752Speter } 788752Speter # endif PTREE 789752Speter # ifdef OBJ 790752Speter if (cbn== 1 && monflg != 0) { 791752Speter patchfil(cntpatch - 2, cnts, 2); 792752Speter patchfil(nfppatch - 2, pfcnt, 2); 793752Speter } 794752Speter # endif OBJ 795752Speter # ifdef PC 796752Speter if ( fp -> class == PROG && monflg ) { 797752Speter putleaf( P2ICON , 0 , 0 , ADDTYPE( P2FTN | P2INT , P2PTR ) 798752Speter , "_PMFLUSH" ); 799752Speter putleaf( P2ICON , cnts , 0 , P2INT , 0 ); 800752Speter putleaf( P2ICON , pfcnt , 0 , P2INT , 0 ); 801752Speter putop( P2LISTOP , P2INT ); 8022068Smckusic putLV( PCPCOUNT , 0 , 0 , P2INT ); 8032068Smckusic putop( P2LISTOP , P2INT ); 804752Speter putop( P2CALL , P2INT ); 805752Speter putdot( filename , line ); 806752Speter } 807752Speter # endif PC 808752Speter if (fp->class == PROG && inp == 0 && (input->nl_flags & (NUSED|NMOD)) != 0) { 809752Speter recovered(); 810752Speter error("Input is used but not defined in the program statement"); 811752Speter } 812752Speter /* 813752Speter * Clean up the symbol table displays and check for unresolves 814752Speter */ 815752Speter line = endline; 816752Speter b = cbn; 817752Speter Fp = fp; 818752Speter chkref = syneflg == errcnt[cbn] && opt('w') == 0; 819752Speter for (i = 0; i <= 077; i++) { 820752Speter for (p = disptab[i]; p != NIL && (p->nl_block & 037) == b; p = p->nl_next) { 821752Speter /* 822752Speter * Check for variables defined 823752Speter * but not referenced 824752Speter */ 825752Speter if (chkref && p->symbol != NIL) 826752Speter switch (p->class) { 827752Speter case FIELD: 828752Speter /* 829752Speter * If the corresponding record is 830752Speter * unused, we shouldn't complain about 831752Speter * the fields. 832752Speter */ 833752Speter default: 834752Speter if ((p->nl_flags & (NUSED|NMOD)) == 0) { 835752Speter warning(); 836752Speter nerror("%s %s is neither used nor set", classes[p->class], p->symbol); 837752Speter break; 838752Speter } 839752Speter /* 840752Speter * If a var parameter is either 841752Speter * modified or used that is enough. 842752Speter */ 843752Speter if (p->class == REF) 844752Speter continue; 845752Speter # ifdef OBJ 846752Speter if ((p->nl_flags & NUSED) == 0) { 847752Speter warning(); 848752Speter nerror("%s %s is never used", classes[p->class], p->symbol); 849752Speter break; 850752Speter } 851752Speter # endif OBJ 852752Speter # ifdef PC 853752Speter if (((p->nl_flags & NUSED) == 0) && ((p->ext_flags & NEXTERN) == 0)) { 854752Speter warning(); 855752Speter nerror("%s %s is never used", classes[p->class], p->symbol); 856752Speter break; 857752Speter } 858752Speter # endif PC 859752Speter if ((p->nl_flags & NMOD) == 0) { 860752Speter warning(); 861752Speter nerror("%s %s is used but never set", classes[p->class], p->symbol); 862752Speter break; 863752Speter } 864752Speter case LABEL: 865752Speter case FVAR: 866752Speter case BADUSE: 867752Speter break; 868752Speter } 869752Speter switch (p->class) { 870752Speter case BADUSE: 871752Speter cp = "s"; 872752Speter if (p->chain->ud_next == NIL) 873752Speter cp++; 874752Speter eholdnl(); 875752Speter if (p->value[NL_KINDS] & ISUNDEF) 876752Speter nerror("%s undefined on line%s", p->symbol, cp); 877752Speter else 878752Speter nerror("%s improperly used on line%s", p->symbol, cp); 879752Speter pnumcnt = 10; 880752Speter pnums(p->chain); 881752Speter pchr('\n'); 882752Speter break; 883752Speter 884752Speter case FUNC: 885752Speter case PROC: 886752Speter # ifdef OBJ 887752Speter if ((p->nl_flags & NFORWD)) 888752Speter nerror("Unresolved forward declaration of %s %s", classes[p->class], p->symbol); 889752Speter # endif OBJ 890752Speter # ifdef PC 891752Speter if ((p->nl_flags & NFORWD) && ((p->ext_flags & NEXTERN) == 0)) 892752Speter nerror("Unresolved forward declaration of %s %s", classes[p->class], p->symbol); 893752Speter # endif PC 894752Speter break; 895752Speter 896752Speter case LABEL: 897752Speter if (p->nl_flags & NFORWD) 898752Speter nerror("label %s was declared but not defined", p->symbol); 899752Speter break; 900752Speter case FVAR: 901752Speter if ((p->nl_flags & NMOD) == 0) 902752Speter nerror("No assignment to the function variable"); 903752Speter break; 904752Speter } 905752Speter } 906752Speter /* 907752Speter * Pop this symbol 908752Speter * table slot 909752Speter */ 910752Speter disptab[i] = p; 911752Speter } 912752Speter 913752Speter # ifdef OBJ 914752Speter put(1, O_END); 915752Speter # endif OBJ 916752Speter # ifdef PC 917752Speter /* 918752Speter * if there were file variables declared at this level 919752Speter * call pclose( &__disply[ cbn ] ) to clean them up. 920752Speter */ 921752Speter if ( dfiles[ cbn ] ) { 922752Speter putleaf( P2ICON , 0 , 0 , ADDTYPE( P2FTN | P2INT , P2PTR ) 923752Speter , "_PCLOSE" ); 924752Speter putRV( DISPLAYNAME , 0 , cbn * sizeof( struct dispsave ) 925752Speter , P2PTR | P2CHAR ); 926752Speter putop( P2CALL , P2INT ); 927752Speter putdot( filename , line ); 928752Speter } 929752Speter /* 930752Speter * if this is a function, 931752Speter * the function variable is the return value. 932752Speter * if it's a scalar valued function, return scalar, 933752Speter * else, return a pointer to the structure value. 934752Speter */ 935752Speter if ( fp -> class == FUNC ) { 936752Speter struct nl *fvar = fp -> ptr[ NL_FVAR ]; 937752Speter long fvartype = p2type( fvar -> type ); 9381196Speter long label; 9391196Speter char labelname[ BUFSIZ ]; 940752Speter 941752Speter switch ( classify( fvar -> type ) ) { 942752Speter case TBOOL: 943752Speter case TCHAR: 944752Speter case TINT: 945752Speter case TSCAL: 946752Speter case TDOUBLE: 947752Speter case TPTR: 948752Speter putRV( fvar -> symbol , ( fvar -> nl_block ) & 037 949752Speter , fvar -> value[ NL_OFFS ] , fvartype ); 950752Speter break; 951752Speter default: 9521196Speter label = getlab(); 9531196Speter sprintf( labelname , PREFIXFORMAT , 9541196Speter LABELPREFIX , label ); 9551196Speter putprintf( " .data" , 0 ); 9561196Speter putprintf( " .lcomm %s,%d" , 0 , 9571196Speter labelname , lwidth( fvar -> type ) ); 9581196Speter putprintf( " .text" , 0 ); 9591374Speter putleaf( P2NAME , 0 , 0 , fvartype , labelname ); 960752Speter putLV( fvar -> symbol , ( fvar -> nl_block ) & 037 961752Speter , fvar -> value[ NL_OFFS ] , fvartype ); 9621196Speter putstrop( P2STASG , fvartype , lwidth( fvar -> type ) , 9631196Speter align( fvar -> type ) ); 9641374Speter putdot( filename , line ); 9651374Speter putleaf( P2ICON , 0 , 0 , fvartype , labelname ); 966752Speter break; 967752Speter } 968752Speter putop( P2FORCE , fvartype ); 969752Speter putdot( filename , line ); 970752Speter } 971752Speter /* 972752Speter * restore old display entry from save area 973752Speter */ 974752Speter 975752Speter putprintf( " movq %d(%s),%s+%d" , 0 976752Speter , DSAVEOFFSET , P2FPNAME 977752Speter , DISPLAYNAME , cbn * sizeof(struct dispsave) ); 978752Speter stabrbrac( cbn ); 979752Speter putprintf( " ret" , 0 ); 980752Speter /* 981752Speter * let the second pass allocate locals 982752Speter */ 983752Speter putlab( botlabel ); 984752Speter putprintf( " subl2 $LF%d,sp" , 0 , ftnno ); 985752Speter putrbracket( ftnno ); 986752Speter putjbr( toplabel ); 987752Speter /* 988752Speter * declare pcp counters, if any 989752Speter */ 990752Speter if ( monflg && fp -> class == PROG ) { 991752Speter putprintf( " .data" , 0 ); 992752Speter putprintf( " .comm " , 1 ); 993752Speter putprintf( PCPCOUNT , 1 ); 994752Speter putprintf( ",%d" , 0 , ( cnts + 1 ) * sizeof (long) ); 995752Speter putprintf( " .text" , 0 ); 996752Speter } 997752Speter # endif PC 998752Speter #ifdef DEBUG 999752Speter dumpnl(fp->ptr[2], fp->symbol); 1000752Speter #endif 1001752Speter /* 1002752Speter * Restore the 1003752Speter * (virtual) name list 1004752Speter * position 1005752Speter */ 1006752Speter nlfree(fp->ptr[2]); 1007752Speter /* 1008752Speter * Proc/func has been 1009752Speter * resolved 1010752Speter */ 1011752Speter fp->nl_flags &= ~NFORWD; 1012752Speter /* 1013752Speter * Patch the beg 1014752Speter * of the proc/func to 1015752Speter * the proper variable size 1016752Speter */ 1017752Speter if (Fp == NIL) 1018752Speter elineon(); 1019752Speter # ifdef OBJ 10202103Smckusic patchfil(var, -sizes[cbn].om_max, 2); 1021752Speter # endif OBJ 1022752Speter cbn--; 1023752Speter if (inpflist(fp->symbol)) { 1024752Speter opop('l'); 1025752Speter } 1026752Speter } 1027752Speter 1028752Speter 1029752Speter /* 1030752Speter * Segend is called to check for 1031752Speter * unresolved variables, funcs and 1032752Speter * procs, and deliver unresolved and 1033752Speter * baduse error diagnostics at the 1034752Speter * end of a routine segment (a separately 1035752Speter * compiled segment that is not the 1036752Speter * main program) for PC. This 1037752Speter * routine should only be called 1038752Speter * by PC (not standard). 1039752Speter */ 1040752Speter segend() 1041752Speter { 1042752Speter register struct nl *p; 1043752Speter register int i,b; 1044752Speter char *cp; 1045752Speter 1046752Speter #ifdef PC 1047752Speter if (opt('s')) { 1048752Speter standard(); 1049752Speter error("Separately compiled routine segments are not standard."); 1050752Speter } else { 1051752Speter b = cbn; 1052752Speter for (i=0; i<077; i++) { 1053752Speter for (p = disptab[i]; p != NIL && (p->nl_block & 037) == b; p = p->nl_next) { 1054752Speter switch (p->class) { 1055752Speter case BADUSE: 1056752Speter cp = 's'; 1057752Speter if (p->chain->ud_next == NIL) 1058752Speter cp++; 1059752Speter eholdnl(); 1060752Speter if (p->value[NL_KINDS] & ISUNDEF) 1061752Speter nerror("%s undefined on line%s", p->symbol, cp); 1062752Speter else 1063752Speter nerror("%s improperly used on line%s", p->symbol, cp); 1064752Speter pnumcnt = 10; 1065752Speter pnums(p->chain); 1066752Speter pchr('\n'); 1067752Speter break; 1068752Speter 1069752Speter case FUNC: 1070752Speter case PROC: 1071752Speter if ((p->nl_flags & NFORWD) && ((p->ext_flags & NEXTERN) == 0)) 1072752Speter nerror("Unresolved forward declaration of %s %s", classes[p->class], p->symbol); 1073752Speter break; 1074752Speter 1075752Speter case FVAR: 1076752Speter if (((p->nl_flags & NMOD) == 0) && ((p->chain->ext_flags & NEXTERN) == 0)) 1077752Speter nerror("No assignment to the function variable"); 1078752Speter break; 1079752Speter } 1080752Speter } 1081752Speter disptab[i] = p; 1082752Speter } 1083752Speter } 1084752Speter #endif PC 1085752Speter #ifdef OBJ 1086752Speter error("Missing program statement and program body"); 1087752Speter #endif OBJ 1088752Speter 1089752Speter } 1090752Speter 1091752Speter 1092752Speter /* 1093752Speter * Level1 does level one processing for 1094752Speter * separately compiled routine segments 1095752Speter */ 1096752Speter level1() 1097752Speter { 1098752Speter 1099752Speter # ifdef OBJ 1100752Speter error("Missing program statement"); 1101752Speter # endif OBJ 1102752Speter # ifdef PC 1103752Speter if (opt('s')) { 1104752Speter standard(); 1105752Speter error("Missing program statement"); 1106752Speter } 1107752Speter # endif PC 1108752Speter 1109752Speter cbn++; 1110752Speter sizes[cbn].om_max = sizes[cbn].om_off = -DPOFF1; 1111834Speter gotos[cbn] = NIL; 1112834Speter errcnt[cbn] = syneflg; 1113834Speter parts[ cbn ] = NIL; 1114834Speter dfiles[ cbn ] = FALSE; 1115752Speter progseen++; 1116752Speter } 1117752Speter 1118752Speter 1119752Speter 1120752Speter pnums(p) 1121752Speter struct udinfo *p; 1122752Speter { 1123752Speter 1124752Speter if (p->ud_next != NIL) 1125752Speter pnums(p->ud_next); 1126752Speter if (pnumcnt == 0) { 1127752Speter printf("\n\t"); 1128752Speter pnumcnt = 20; 1129752Speter } 1130752Speter pnumcnt--; 1131752Speter printf(" %d", p->ud_line); 1132752Speter } 1133752Speter 1134752Speter nerror(a1, a2, a3) 1135752Speter { 1136752Speter 1137752Speter if (Fp != NIL) { 1138752Speter yySsync(); 1139752Speter #ifndef PI1 1140752Speter if (opt('l')) 1141752Speter yyoutline(); 1142752Speter #endif 1143752Speter yysetfile(filename); 1144752Speter printf("In %s %s:\n", classes[Fp->class], Fp->symbol); 1145752Speter Fp = NIL; 1146752Speter elineoff(); 1147752Speter } 1148752Speter error(a1, a2, a3); 1149752Speter } 1150