1752Speter /* Copyright (c) 1979 Regents of the University of California */ 2752Speter 3*3073Smckusic static char sccsid[] = "@(#)fdec.c 1.13 1/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; 47*3073Smckusic int w, 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: 106*3073Smckusic progseen = TRUE; 107752Speter if (opt('z')) 108*3073Smckusic monflg = TRUE; 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 187*3073Smckusic cp = defnl(r[2], FVAR, p->type, 188*3073Smckusic -(roundup((int)(DPOFF1+lwidth(p->type)), 189*3073Smckusic (long)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 240*3073Smckusic w = width(p); 241*3073Smckusic o -= even(w); 242*3073Smckusic # ifdef DEC11 243*3073Smckusic dp = defnl(il[1], VAR, p, o); 244*3073Smckusic # else 245*3073Smckusic dp = defnl(il[1], VAR, p, 246*3073Smckusic (w < 2) ? o + 1 : o); 247*3073Smckusic # endif DEC11 248752Speter # endif OBJ 249752Speter # ifdef PC 250752Speter dp = defnl( il[1] , VAR , p 251*3073Smckusic , o = roundup( o , (long)A_STACK ) ); 252752Speter o += width( p ); 253752Speter # endif PC 254752Speter dp->nl_flags |= NMOD; 255752Speter break; 256752Speter case T_PVAR: 257752Speter # ifdef OBJ 258752Speter dp = defnl(il[1], REF, p, o -= sizeof ( int * ) ); 259752Speter # endif OBJ 260752Speter # ifdef PC 261752Speter dp = defnl( il[1] , REF , p 262*3073Smckusic , o = roundup( o , (long)A_STACK ) ); 263752Speter o += sizeof(char *); 264752Speter # endif PC 265752Speter break; 266752Speter case T_PFUNC: 2671196Speter # ifdef OBJ 2681196Speter dp = defnl(il[1], FFUNC, p, o -= sizeof ( int * ) ); 2691196Speter # endif OBJ 2701196Speter # ifdef PC 2711196Speter dp = defnl( il[1] , FFUNC , p 272*3073Smckusic , o = roundup( o , (long)A_STACK ) ); 2731196Speter o += sizeof(char *); 2741196Speter # endif PC 2751196Speter dp -> nl_flags |= NMOD; 2761196Speter break; 277752Speter case T_PPROC: 2781196Speter # ifdef OBJ 2791196Speter dp = defnl(il[1], FPROC, p, o -= sizeof ( int * ) ); 2801196Speter # endif OBJ 2811196Speter # ifdef PC 2821196Speter dp = defnl( il[1] , FPROC , p 283*3073Smckusic , o = roundup( o , (long)A_STACK ) ); 2841196Speter o += sizeof(char *); 2851196Speter # endif PC 2861196Speter dp -> nl_flags |= NMOD; 2871196Speter break; 288752Speter } 289752Speter if (dp != NIL) { 290752Speter cp->chain = dp; 291752Speter cp = dp; 292752Speter } 293752Speter } 294752Speter } 295752Speter cbn--; 296752Speter p = sp; 297752Speter # ifdef OBJ 298752Speter p->value[NL_OFFS] = -o+DPOFF2; 299752Speter /* 300752Speter * Correct the naivete (naievity) 301752Speter * of our above code to 302752Speter * calculate offsets 303752Speter */ 304752Speter for (il = p->chain; il != NIL; il = il->chain) 305752Speter il->value[NL_OFFS] += p->value[NL_OFFS]; 306752Speter # endif OBJ 307752Speter # ifdef PC 308*3073Smckusic p -> value[ NL_OFFS ] = roundup( o , (long)A_STACK ); 309752Speter # endif PC 310752Speter } else { 311752Speter /* 312752Speter * The wonderful 313752Speter * program statement! 314752Speter */ 315752Speter # ifdef OBJ 316752Speter if (monflg) { 317752Speter put(1, O_PXPBUF); 318*3073Smckusic cntpatch = put(2, O_CASE4, (long)0); 319*3073Smckusic nfppatch = put(2, O_CASE4, (long)0); 320752Speter } 321752Speter # endif OBJ 322752Speter cp = p; 323752Speter for (rl = r[3]; rl; rl = rl[2]) { 324752Speter if (rl[1] == NIL) 325752Speter continue; 326752Speter dp = defnl(rl[1], VAR, 0, 0); 327752Speter cp->chain = dp; 328752Speter cp = dp; 329752Speter } 330752Speter } 331752Speter /* 332752Speter * Define a branch at 333752Speter * the "entry point" of 334752Speter * the prog/proc/func. 335752Speter */ 336752Speter p->entloc = getlab(); 337752Speter if (monflg) { 338752Speter bodycnts[ cbn ] = getcnt(); 339752Speter p->value[ NL_CNTR ] = 0; 340752Speter } 341752Speter # ifdef OBJ 342*3073Smckusic put(2, O_TRA4, (long)p->entloc); 343752Speter # endif OBJ 344752Speter # ifdef PTREE 345752Speter { 346752Speter pPointer PF = tCopy( r ); 347752Speter 348752Speter pSeize( PorFHeader[ nesting ] ); 349752Speter if ( r[0] != T_PROG ) { 350752Speter pPointer *PFs; 351752Speter 352752Speter PFs = &( pDEF( PorFHeader[ nesting ] ).PorFPFs ); 353752Speter *PFs = ListAppend( *PFs , PF ); 354752Speter } else { 355752Speter pDEF( PorFHeader[ nesting ] ).GlobProg = PF; 356752Speter } 357752Speter pRelease( PorFHeader[ nesting ] ); 358752Speter } 359752Speter # endif PTREE 360752Speter return (p); 361752Speter } 362752Speter 363752Speter funcfwd(fp) 364752Speter struct nl *fp; 365752Speter { 366752Speter 367752Speter /* 368752Speter * save the counter for this function 369752Speter */ 370752Speter if ( monflg ) { 371752Speter fp -> value[ NL_CNTR ] = bodycnts[ cbn ]; 372752Speter } 373752Speter return (fp); 374752Speter } 375752Speter 376752Speter /* 377752Speter * Funcext marks the procedure or 378752Speter * function external in the symbol 379752Speter * table. Funcext should only be 380752Speter * called if PC, and is an error 381752Speter * otherwise. 382752Speter */ 383752Speter 384752Speter funcext(fp) 385752Speter struct nl *fp; 386752Speter { 387752Speter 388752Speter #ifdef PC 389752Speter if (opt('s')) { 390752Speter standard(); 391752Speter error("External procedures and functions are not standard"); 392752Speter } else { 393752Speter if (cbn == 1) { 394752Speter fp->ext_flags |= NEXTERN; 395825Speter stabefunc( fp -> symbol , fp -> class , line ); 396752Speter } 397752Speter else 398752Speter error("External procedures and functions can only be declared at the outermost level."); 399752Speter } 400752Speter #endif PC 401752Speter #ifdef OBJ 402752Speter error("Procedures or functions cannot be declared external."); 403752Speter #endif OBJ 404752Speter 405752Speter return(fp); 406752Speter } 407752Speter 408752Speter /* 409752Speter * Funcbody is called 410752Speter * when the actual (resolved) 411752Speter * declaration of a procedure is 412752Speter * encountered. It puts the names 413752Speter * of the (function) and parameters 414752Speter * into the symbol table. 415752Speter */ 416752Speter funcbody(fp) 417752Speter struct nl *fp; 418752Speter { 419752Speter register struct nl *q, *p; 420752Speter 421752Speter cbn++; 422752Speter if (cbn >= DSPLYSZ) { 423752Speter error("Too many levels of function/procedure nesting"); 424752Speter pexit(ERRS); 425752Speter } 426752Speter sizes[cbn].om_max = sizes[cbn].om_off = -DPOFF1; 427752Speter gotos[cbn] = NIL; 428752Speter errcnt[cbn] = syneflg; 429834Speter parts[ cbn ] = NIL; 430752Speter dfiles[ cbn ] = FALSE; 431752Speter if (fp == NIL) 432752Speter return (NIL); 433752Speter /* 434752Speter * Save the virtual name 435752Speter * list stack pointer so 436752Speter * the space can be freed 437752Speter * later (funcend). 438752Speter */ 439752Speter fp->ptr[2] = nlp; 440752Speter if (fp->class != PROG) { 441752Speter for (q = fp->chain; q != NIL; q = q->chain) { 442752Speter enter(q); 443752Speter } 444752Speter } 445752Speter if (fp->class == FUNC) { 446752Speter /* 447752Speter * For functions, enter the fvar 448752Speter */ 449752Speter enter(fp->ptr[NL_FVAR]); 450752Speter # ifdef PC 451752Speter q = fp -> ptr[ NL_FVAR ]; 452752Speter sizes[cbn].om_off -= lwidth( q -> type ); 453752Speter sizes[cbn].om_max = sizes[cbn].om_off; 454752Speter # endif PC 455752Speter } 456752Speter # ifdef PTREE 457752Speter /* 458752Speter * pick up the pointer to porf declaration 459752Speter */ 460752Speter PorFHeader[ ++nesting ] = fp -> inTree; 461752Speter # endif PTREE 462752Speter return (fp); 463752Speter } 464752Speter 465752Speter struct nl *Fp; 466752Speter int pnumcnt; 467752Speter /* 468752Speter * Funcend is called to 469752Speter * finish a block by generating 470752Speter * the code for the statements. 471752Speter * It then looks for unresolved declarations 472752Speter * of labels, procedures and functions, 473752Speter * and cleans up the name list. 474752Speter * For the program, it checks the 475752Speter * semantics of the program 476752Speter * statement (yuchh). 477752Speter */ 478752Speter funcend(fp, bundle, endline) 479752Speter struct nl *fp; 480752Speter int *bundle; 481752Speter int endline; 482752Speter { 483752Speter register struct nl *p; 484752Speter register int i, b; 485*3073Smckusic int var, inp, out, *blk; 486*3073Smckusic bool chkref; 487752Speter struct nl *iop; 488752Speter char *cp; 489752Speter extern int cntstat; 490752Speter # ifdef PC 491752Speter int toplabel = getlab(); 492752Speter int botlabel = getlab(); 493752Speter # endif PC 494752Speter 495752Speter cntstat = 0; 496752Speter /* 497752Speter * yyoutline(); 498752Speter */ 499752Speter if (program != NIL) 500752Speter line = program->value[3]; 501752Speter blk = bundle[2]; 502752Speter if (fp == NIL) { 503752Speter cbn--; 504752Speter # ifdef PTREE 505752Speter nesting--; 506752Speter # endif PTREE 507752Speter return; 508752Speter } 509752Speter #ifdef OBJ 510752Speter /* 511752Speter * Patch the branch to the 512752Speter * entry point of the function 513752Speter */ 514752Speter patch4(fp->entloc); 515752Speter /* 516752Speter * Put out the block entrance code and the block name. 5172220Smckusic * HDRSZE is the number of bytes of info in the static 5182220Smckusic * BEG data area exclusive of the proc name. It is 5192220Smckusic * currently defined as: 5202220Smckusic /* struct hdr { 5212220Smckusic /* long framesze; /* number of bytes of local vars */ 5222220Smckusic /* long nargs; /* number of bytes of arguments */ 523*3073Smckusic /* bool tests; /* TRUE => perform runtime tests */ 5242220Smckusic /* short offset; /* offset of procedure in source file */ 5252220Smckusic /* char name[1]; /* name of active procedure */ 5262220Smckusic /* }; 527752Speter */ 528*3073Smckusic # define HDRSZE (2 * sizeof(long) + sizeof(short) + sizeof(bool)) 529*3073Smckusic var = put(2, ((lenstr(fp->symbol,0) + HDRSZE) << 8) 530*3073Smckusic | (cbn == 1 && opt('p') == 0 ? O_NODUMP: O_BEG), (long)0); 5311196Speter /* 5321196Speter * output the number of bytes of arguments 5331196Speter * this is only checked on formal calls. 5341196Speter */ 535*3073Smckusic put(2, O_CASE4, cbn == 1 ? (long)0 : (long)(fp->value[NL_OFFS]-DPOFF2)); 5362190Smckusic /* 5372190Smckusic * Output the runtime test mode for the routine 5382190Smckusic */ 539*3073Smckusic put(2, sizeof(bool) == 2 ? O_CASE2 : O_CASE4, opt('t') ? TRUE : FALSE); 5402190Smckusic /* 5412190Smckusic * Output line number and routine name 5422190Smckusic */ 543752Speter put(2, O_CASE2, bundle[1]); 544752Speter putstr(fp->symbol, 0); 545752Speter #endif OBJ 546752Speter #ifdef PC 547752Speter /* 548752Speter * put out the procedure entry code 549752Speter */ 550752Speter if ( fp -> class == PROG ) { 551752Speter putprintf( " .text" , 0 ); 552752Speter putprintf( " .align 1" , 0 ); 553752Speter putprintf( " .globl _main" , 0 ); 554752Speter putprintf( "_main:" , 0 ); 555752Speter putprintf( " .word 0" , 0 ); 556752Speter putprintf( " calls $0,_PCSTART" , 0 ); 557752Speter putprintf( " movl 4(ap),__argc" , 0 ); 558752Speter putprintf( " movl 8(ap),__argv" , 0 ); 559752Speter putprintf( " calls $0,_program" , 0 ); 560752Speter putprintf( " calls $0,_PCEXIT" , 0 ); 561752Speter ftnno = fp -> entloc; 562752Speter putprintf( " .text" , 0 ); 563752Speter putprintf( " .align 1" , 0 ); 564752Speter putprintf( " .globl _program" , 0 ); 565752Speter putprintf( "_program:" , 0 ); 5662163Speter stabfunc( "program" , fp -> class , bundle[1] , 0 ); 567752Speter } else { 568752Speter ftnno = fp -> entloc; 569752Speter putprintf( " .text" , 0 ); 570752Speter putprintf( " .align 1" , 0 ); 571752Speter putprintf( " .globl " , 1 ); 572752Speter for ( i = 1 ; i < cbn ; i++ ) { 573752Speter putprintf( EXTFORMAT , 1 , enclosing[ i ] ); 574752Speter } 575752Speter putprintf( "" , 0 ); 576752Speter for ( i = 1 ; i < cbn ; i++ ) { 577752Speter putprintf( EXTFORMAT , 1 , enclosing[ i ] ); 578752Speter } 579752Speter putprintf( ":" , 0 ); 5802163Speter stabfunc( fp -> symbol , fp -> class , bundle[1] , cbn - 1 ); 5812163Speter for ( p = fp -> chain ; p != NIL ; p = p -> chain ) { 5822163Speter stabparam( p -> symbol , p2type( p -> type ) 5832163Speter , p -> value[ NL_OFFS ] , lwidth( p -> type ) ); 5842163Speter } 5852163Speter if ( fp -> class == FUNC ) { 5862163Speter /* 5872163Speter * stab the function variable 5882163Speter */ 5892163Speter p = fp -> ptr[ NL_FVAR ]; 5902163Speter stablvar( p -> symbol , p2type( p -> type ) , cbn 5912163Speter , p -> value[ NL_OFFS ] , lwidth( p -> type ) ); 5922163Speter } 5932163Speter /* 5942163Speter * stab local variables 5952163Speter * rummage down hash chain links. 5962163Speter */ 5972163Speter for ( i = 0 ; i <= 077 ; i++ ) { 5982163Speter for ( p = disptab[ i ] ; p != NIL ; p = p->nl_next) { 5992163Speter if ( ( p -> nl_block & 037 ) != cbn ) { 6002163Speter break; 6012163Speter } 6022163Speter /* 6032163Speter * stab local variables 6042163Speter * that's named variables, but not params 6052163Speter */ 6062163Speter if ( ( p -> symbol != NIL ) 6072163Speter && ( p -> class == VAR ) 6082163Speter && ( p -> value[ NL_OFFS ] < 0 ) ) { 6092163Speter stablvar( p -> symbol , p2type( p -> type ) , cbn 6102163Speter , p -> value[ NL_OFFS ] , lwidth( p -> type ) ); 6112163Speter } 6122163Speter } 6132163Speter } 614752Speter } 615752Speter stablbrac( cbn ); 616752Speter /* 617752Speter * register save mask 618752Speter */ 619752Speter if ( opt( 't' ) ) { 620752Speter putprintf( " .word 0x%x" , 0 , RUNCHECK | RSAVEMASK ); 621752Speter } else { 622752Speter putprintf( " .word 0x%x" , 0 , RSAVEMASK ); 623752Speter } 624752Speter putjbr( botlabel ); 625752Speter putlab( toplabel ); 626752Speter if ( profflag ) { 627752Speter /* 628752Speter * call mcount for profiling 629752Speter */ 630752Speter putprintf( " moval 1f,r0" , 0 ); 631752Speter putprintf( " jsb mcount" , 0 ); 632752Speter putprintf( " .data" , 0 ); 633752Speter putprintf( " .align 2" , 0 ); 634752Speter putprintf( "1:" , 0 ); 635752Speter putprintf( " .long 0" , 0 ); 636752Speter putprintf( " .text" , 0 ); 637752Speter } 638752Speter /* 639752Speter * set up unwind exception vector. 640752Speter */ 641752Speter putprintf( " moval %s,%d(%s)" , 0 642752Speter , UNWINDNAME , UNWINDOFFSET , P2FPNAME ); 643752Speter /* 644752Speter * save address of display entry, for unwind. 645752Speter */ 646752Speter putprintf( " moval %s+%d,%d(%s)" , 0 647752Speter , DISPLAYNAME , cbn * sizeof(struct dispsave) 648752Speter , DPTROFFSET , P2FPNAME ); 649752Speter /* 650752Speter * save old display 651752Speter */ 652752Speter putprintf( " movq %s+%d,%d(%s)" , 0 653752Speter , DISPLAYNAME , cbn * sizeof(struct dispsave) 654752Speter , DSAVEOFFSET , P2FPNAME ); 655752Speter /* 656752Speter * set up new display by saving AP and FP in appropriate 657752Speter * slot in display structure. 658752Speter */ 659752Speter putprintf( " movq %s,%s+%d" , 0 660752Speter , P2APNAME , DISPLAYNAME , cbn * sizeof(struct dispsave) ); 661752Speter /* 662752Speter * ask second pass to allocate known locals 663752Speter */ 664752Speter putlbracket( ftnno , -sizes[ cbn ].om_max ); 665752Speter /* 666752Speter * and zero them if checking is on 6672125Smckusic * by calling blkclr( bytes of locals , starting local address ); 668752Speter */ 6691196Speter if ( opt( 't' ) ) { 6701196Speter if ( ( -sizes[ cbn ].om_max ) > DPOFF1 ) { 6711196Speter putleaf( P2ICON , 0 , 0 , ADDTYPE( P2FTN | P2INT , P2PTR ) 6722125Smckusic , "_blkclr" ); 6731196Speter putleaf( P2ICON , ( -sizes[ cbn ].om_max ) - DPOFF1 6741196Speter , 0 , P2INT , 0 ); 6751196Speter putLV( 0 , cbn , sizes[ cbn ].om_max , P2CHAR ); 6761196Speter putop( P2LISTOP , P2INT ); 6771196Speter putop( P2CALL , P2INT ); 6781196Speter putdot( filename , line ); 6791196Speter } 6801196Speter /* 6811196Speter * check number of longs of arguments 6821196Speter * this can only be wrong for formal calls. 6831196Speter */ 6841196Speter if ( fp -> class != PROG ) { 6851196Speter putleaf( P2ICON , 0 , 0 , ADDTYPE( P2PTR , P2FTN | P2INT ) , 6861196Speter "_NARGCHK" ); 6871196Speter putleaf( P2ICON , 6881196Speter (fp->value[NL_OFFS] - DPOFF2) / sizeof(long) , 6891196Speter 0 , P2INT , 0 ); 6901196Speter putop( P2CALL , P2INT ); 6911196Speter putdot( filename , line ); 6921196Speter } 693752Speter } 694752Speter #endif PC 695752Speter if ( monflg ) { 696752Speter if ( fp -> value[ NL_CNTR ] != 0 ) { 697752Speter inccnt( fp -> value [ NL_CNTR ] ); 698752Speter } 699752Speter inccnt( bodycnts[ fp -> nl_block & 037 ] ); 700752Speter } 701752Speter if (fp->class == PROG) { 702752Speter /* 703752Speter * The glorious buffers option. 704752Speter * 0 = don't buffer output 705752Speter * 1 = line buffer output 706752Speter * 2 = 512 byte buffer output 707752Speter */ 708752Speter # ifdef OBJ 709752Speter if (opt('b') != 1) 710752Speter put(1, O_BUFF | opt('b') << 8); 711752Speter # endif OBJ 712752Speter # ifdef PC 713752Speter if ( opt( 'b' ) != 1 ) { 714752Speter putleaf( P2ICON , 0 , 0 715752Speter , ADDTYPE( P2FTN | P2INT , P2PTR ) , "_BUFF" ); 716752Speter putleaf( P2ICON , opt( 'b' ) , 0 , P2INT , 0 ); 717752Speter putop( P2CALL , P2INT ); 718752Speter putdot( filename , line ); 719752Speter } 720752Speter # endif PC 721752Speter out = 0; 722752Speter for (p = fp->chain; p != NIL; p = p->chain) { 723752Speter if (strcmp(p->symbol, "input") == 0) { 724752Speter inp++; 725752Speter continue; 726752Speter } 727752Speter if (strcmp(p->symbol, "output") == 0) { 728752Speter out++; 729752Speter continue; 730752Speter } 731752Speter iop = lookup1(p->symbol); 732752Speter if (iop == NIL || bn != cbn) { 733752Speter error("File %s listed in program statement but not declared", p->symbol); 734752Speter continue; 735752Speter } 736752Speter if (iop->class != VAR) { 737752Speter error("File %s listed in program statement but declared as a %s", p->symbol, classes[iop->class]); 738752Speter continue; 739752Speter } 740752Speter if (iop->type == NIL) 741752Speter continue; 742752Speter if (iop->type->class != FILET) { 743752Speter error("File %s listed in program statement but defined as %s", 744752Speter p->symbol, nameof(iop->type)); 745752Speter continue; 746752Speter } 747752Speter # ifdef OBJ 7482068Smckusic put(2, O_CON24, text(iop->type) ? 0 : width(iop->type->type)); 749752Speter i = lenstr(p->symbol,0); 7502068Smckusic put(2, O_CON24, i); 751752Speter put(2, O_LVCON, i); 752752Speter putstr(p->symbol, 0); 753*3073Smckusic put(2, O_LV | bn<<8+INDX, (int)iop->value[NL_OFFS]); 754752Speter put(1, O_DEFNAME); 755752Speter # endif OBJ 756752Speter # ifdef PC 757752Speter putleaf( P2ICON , 0 , 0 758752Speter , ADDTYPE( P2FTN | P2INT , P2PTR ) 759752Speter , "_DEFNAME" ); 760752Speter putLV( p -> symbol , bn , iop -> value[NL_OFFS] 761752Speter , p2type( iop ) ); 762752Speter putCONG( p -> symbol , strlen( p -> symbol ) 763752Speter , LREQ ); 764752Speter putop( P2LISTOP , P2INT ); 765752Speter putleaf( P2ICON , strlen( p -> symbol ) 766752Speter , 0 , P2INT , 0 ); 767752Speter putop( P2LISTOP , P2INT ); 768752Speter putleaf( P2ICON 769752Speter , text(iop->type) ? 0 : width(iop->type->type) 770752Speter , 0 , P2INT , 0 ); 771752Speter putop( P2LISTOP , P2INT ); 772752Speter putop( P2CALL , P2INT ); 773752Speter putdot( filename , line ); 774752Speter # endif PC 775752Speter } 776752Speter if (out == 0 && fp->chain != NIL) { 777752Speter recovered(); 778752Speter error("The file output must appear in the program statement file list"); 779752Speter } 780752Speter } 781752Speter /* 782752Speter * Process the prog/proc/func body 783752Speter */ 784752Speter noreach = 0; 785752Speter line = bundle[1]; 786752Speter statlist(blk); 787752Speter # ifdef PTREE 788752Speter { 789752Speter pPointer Body = tCopy( blk ); 790752Speter 791752Speter pDEF( PorFHeader[ nesting -- ] ).PorFBody = Body; 792752Speter } 793752Speter # endif PTREE 794752Speter # ifdef OBJ 795752Speter if (cbn== 1 && monflg != 0) { 796*3073Smckusic patchfil(cntpatch - 2, (long)cnts, 2); 797*3073Smckusic patchfil(nfppatch - 2, (long)pfcnt, 2); 798752Speter } 799752Speter # endif OBJ 800752Speter # ifdef PC 801752Speter if ( fp -> class == PROG && monflg ) { 802752Speter putleaf( P2ICON , 0 , 0 , ADDTYPE( P2FTN | P2INT , P2PTR ) 803752Speter , "_PMFLUSH" ); 804752Speter putleaf( P2ICON , cnts , 0 , P2INT , 0 ); 805752Speter putleaf( P2ICON , pfcnt , 0 , P2INT , 0 ); 806752Speter putop( P2LISTOP , P2INT ); 8072068Smckusic putLV( PCPCOUNT , 0 , 0 , P2INT ); 8082068Smckusic putop( P2LISTOP , P2INT ); 809752Speter putop( P2CALL , P2INT ); 810752Speter putdot( filename , line ); 811752Speter } 812752Speter # endif PC 813752Speter if (fp->class == PROG && inp == 0 && (input->nl_flags & (NUSED|NMOD)) != 0) { 814752Speter recovered(); 815752Speter error("Input is used but not defined in the program statement"); 816752Speter } 817752Speter /* 818752Speter * Clean up the symbol table displays and check for unresolves 819752Speter */ 820752Speter line = endline; 821752Speter b = cbn; 822752Speter Fp = fp; 823752Speter chkref = syneflg == errcnt[cbn] && opt('w') == 0; 824752Speter for (i = 0; i <= 077; i++) { 825752Speter for (p = disptab[i]; p != NIL && (p->nl_block & 037) == b; p = p->nl_next) { 826752Speter /* 827752Speter * Check for variables defined 828752Speter * but not referenced 829752Speter */ 830752Speter if (chkref && p->symbol != NIL) 831752Speter switch (p->class) { 832752Speter case FIELD: 833752Speter /* 834752Speter * If the corresponding record is 835752Speter * unused, we shouldn't complain about 836752Speter * the fields. 837752Speter */ 838752Speter default: 839752Speter if ((p->nl_flags & (NUSED|NMOD)) == 0) { 840752Speter warning(); 841752Speter nerror("%s %s is neither used nor set", classes[p->class], p->symbol); 842752Speter break; 843752Speter } 844752Speter /* 845752Speter * If a var parameter is either 846752Speter * modified or used that is enough. 847752Speter */ 848752Speter if (p->class == REF) 849752Speter continue; 850752Speter # ifdef OBJ 851752Speter if ((p->nl_flags & NUSED) == 0) { 852752Speter warning(); 853752Speter nerror("%s %s is never used", classes[p->class], p->symbol); 854752Speter break; 855752Speter } 856752Speter # endif OBJ 857752Speter # ifdef PC 858752Speter if (((p->nl_flags & NUSED) == 0) && ((p->ext_flags & NEXTERN) == 0)) { 859752Speter warning(); 860752Speter nerror("%s %s is never used", classes[p->class], p->symbol); 861752Speter break; 862752Speter } 863752Speter # endif PC 864752Speter if ((p->nl_flags & NMOD) == 0) { 865752Speter warning(); 866752Speter nerror("%s %s is used but never set", classes[p->class], p->symbol); 867752Speter break; 868752Speter } 869752Speter case LABEL: 870752Speter case FVAR: 871752Speter case BADUSE: 872752Speter break; 873752Speter } 874752Speter switch (p->class) { 875752Speter case BADUSE: 876752Speter cp = "s"; 877752Speter if (p->chain->ud_next == NIL) 878752Speter cp++; 879752Speter eholdnl(); 880752Speter if (p->value[NL_KINDS] & ISUNDEF) 881752Speter nerror("%s undefined on line%s", p->symbol, cp); 882752Speter else 883752Speter nerror("%s improperly used on line%s", p->symbol, cp); 884752Speter pnumcnt = 10; 885752Speter pnums(p->chain); 886752Speter pchr('\n'); 887752Speter break; 888752Speter 889752Speter case FUNC: 890752Speter case PROC: 891752Speter # ifdef OBJ 892752Speter if ((p->nl_flags & NFORWD)) 893752Speter nerror("Unresolved forward declaration of %s %s", classes[p->class], p->symbol); 894752Speter # endif OBJ 895752Speter # ifdef PC 896752Speter if ((p->nl_flags & NFORWD) && ((p->ext_flags & NEXTERN) == 0)) 897752Speter nerror("Unresolved forward declaration of %s %s", classes[p->class], p->symbol); 898752Speter # endif PC 899752Speter break; 900752Speter 901752Speter case LABEL: 902752Speter if (p->nl_flags & NFORWD) 903752Speter nerror("label %s was declared but not defined", p->symbol); 904752Speter break; 905752Speter case FVAR: 906752Speter if ((p->nl_flags & NMOD) == 0) 907752Speter nerror("No assignment to the function variable"); 908752Speter break; 909752Speter } 910752Speter } 911752Speter /* 912752Speter * Pop this symbol 913752Speter * table slot 914752Speter */ 915752Speter disptab[i] = p; 916752Speter } 917752Speter 918752Speter # ifdef OBJ 919752Speter put(1, O_END); 920752Speter # endif OBJ 921752Speter # ifdef PC 922752Speter /* 923752Speter * if there were file variables declared at this level 924752Speter * call pclose( &__disply[ cbn ] ) to clean them up. 925752Speter */ 926752Speter if ( dfiles[ cbn ] ) { 927752Speter putleaf( P2ICON , 0 , 0 , ADDTYPE( P2FTN | P2INT , P2PTR ) 928752Speter , "_PCLOSE" ); 929752Speter putRV( DISPLAYNAME , 0 , cbn * sizeof( struct dispsave ) 930752Speter , P2PTR | P2CHAR ); 931752Speter putop( P2CALL , P2INT ); 932752Speter putdot( filename , line ); 933752Speter } 934752Speter /* 935752Speter * if this is a function, 936752Speter * the function variable is the return value. 937752Speter * if it's a scalar valued function, return scalar, 938752Speter * else, return a pointer to the structure value. 939752Speter */ 940752Speter if ( fp -> class == FUNC ) { 941752Speter struct nl *fvar = fp -> ptr[ NL_FVAR ]; 942752Speter long fvartype = p2type( fvar -> type ); 9431196Speter long label; 9441196Speter char labelname[ BUFSIZ ]; 945752Speter 946752Speter switch ( classify( fvar -> type ) ) { 947752Speter case TBOOL: 948752Speter case TCHAR: 949752Speter case TINT: 950752Speter case TSCAL: 951752Speter case TDOUBLE: 952752Speter case TPTR: 953752Speter putRV( fvar -> symbol , ( fvar -> nl_block ) & 037 954752Speter , fvar -> value[ NL_OFFS ] , fvartype ); 955752Speter break; 956752Speter default: 9571196Speter label = getlab(); 9581196Speter sprintf( labelname , PREFIXFORMAT , 9591196Speter LABELPREFIX , label ); 9601196Speter putprintf( " .data" , 0 ); 9611196Speter putprintf( " .lcomm %s,%d" , 0 , 9621196Speter labelname , lwidth( fvar -> type ) ); 9631196Speter putprintf( " .text" , 0 ); 9641374Speter putleaf( P2NAME , 0 , 0 , fvartype , labelname ); 965752Speter putLV( fvar -> symbol , ( fvar -> nl_block ) & 037 966752Speter , fvar -> value[ NL_OFFS ] , fvartype ); 9671196Speter putstrop( P2STASG , fvartype , lwidth( fvar -> type ) , 9681196Speter align( fvar -> type ) ); 9691374Speter putdot( filename , line ); 9701374Speter putleaf( P2ICON , 0 , 0 , fvartype , labelname ); 971752Speter break; 972752Speter } 973752Speter putop( P2FORCE , fvartype ); 974752Speter putdot( filename , line ); 975752Speter } 976752Speter /* 977752Speter * restore old display entry from save area 978752Speter */ 979752Speter 980752Speter putprintf( " movq %d(%s),%s+%d" , 0 981752Speter , DSAVEOFFSET , P2FPNAME 982752Speter , DISPLAYNAME , cbn * sizeof(struct dispsave) ); 983752Speter stabrbrac( cbn ); 984752Speter putprintf( " ret" , 0 ); 985752Speter /* 986752Speter * let the second pass allocate locals 987752Speter */ 988752Speter putlab( botlabel ); 989752Speter putprintf( " subl2 $LF%d,sp" , 0 , ftnno ); 990752Speter putrbracket( ftnno ); 991752Speter putjbr( toplabel ); 992752Speter /* 993752Speter * declare pcp counters, if any 994752Speter */ 995752Speter if ( monflg && fp -> class == PROG ) { 996752Speter putprintf( " .data" , 0 ); 997752Speter putprintf( " .comm " , 1 ); 998752Speter putprintf( PCPCOUNT , 1 ); 999752Speter putprintf( ",%d" , 0 , ( cnts + 1 ) * sizeof (long) ); 1000752Speter putprintf( " .text" , 0 ); 1001752Speter } 1002752Speter # endif PC 1003752Speter #ifdef DEBUG 1004752Speter dumpnl(fp->ptr[2], fp->symbol); 1005752Speter #endif 1006752Speter /* 1007752Speter * Restore the 1008752Speter * (virtual) name list 1009752Speter * position 1010752Speter */ 1011752Speter nlfree(fp->ptr[2]); 1012752Speter /* 1013752Speter * Proc/func has been 1014752Speter * resolved 1015752Speter */ 1016752Speter fp->nl_flags &= ~NFORWD; 1017752Speter /* 1018752Speter * Patch the beg 1019752Speter * of the proc/func to 1020752Speter * the proper variable size 1021752Speter */ 1022752Speter if (Fp == NIL) 1023752Speter elineon(); 1024752Speter # ifdef OBJ 1025*3073Smckusic patchfil(var, (long)(-sizes[cbn].om_max), 2); 1026752Speter # endif OBJ 1027752Speter cbn--; 1028752Speter if (inpflist(fp->symbol)) { 1029752Speter opop('l'); 1030752Speter } 1031752Speter } 1032752Speter 1033752Speter 1034752Speter /* 1035752Speter * Segend is called to check for 1036752Speter * unresolved variables, funcs and 1037752Speter * procs, and deliver unresolved and 1038752Speter * baduse error diagnostics at the 1039752Speter * end of a routine segment (a separately 1040752Speter * compiled segment that is not the 1041752Speter * main program) for PC. This 1042752Speter * routine should only be called 1043752Speter * by PC (not standard). 1044752Speter */ 1045752Speter segend() 1046752Speter { 1047752Speter register struct nl *p; 1048752Speter register int i,b; 1049752Speter char *cp; 1050752Speter 1051752Speter #ifdef PC 1052752Speter if (opt('s')) { 1053752Speter standard(); 1054752Speter error("Separately compiled routine segments are not standard."); 1055752Speter } else { 1056752Speter b = cbn; 1057752Speter for (i=0; i<077; i++) { 1058752Speter for (p = disptab[i]; p != NIL && (p->nl_block & 037) == b; p = p->nl_next) { 1059752Speter switch (p->class) { 1060752Speter case BADUSE: 1061752Speter cp = 's'; 1062752Speter if (p->chain->ud_next == NIL) 1063752Speter cp++; 1064752Speter eholdnl(); 1065752Speter if (p->value[NL_KINDS] & ISUNDEF) 1066752Speter nerror("%s undefined on line%s", p->symbol, cp); 1067752Speter else 1068752Speter nerror("%s improperly used on line%s", p->symbol, cp); 1069752Speter pnumcnt = 10; 1070752Speter pnums(p->chain); 1071752Speter pchr('\n'); 1072752Speter break; 1073752Speter 1074752Speter case FUNC: 1075752Speter case PROC: 1076752Speter if ((p->nl_flags & NFORWD) && ((p->ext_flags & NEXTERN) == 0)) 1077752Speter nerror("Unresolved forward declaration of %s %s", classes[p->class], p->symbol); 1078752Speter break; 1079752Speter 1080752Speter case FVAR: 1081752Speter if (((p->nl_flags & NMOD) == 0) && ((p->chain->ext_flags & NEXTERN) == 0)) 1082752Speter nerror("No assignment to the function variable"); 1083752Speter break; 1084752Speter } 1085752Speter } 1086752Speter disptab[i] = p; 1087752Speter } 1088752Speter } 1089752Speter #endif PC 1090752Speter #ifdef OBJ 1091752Speter error("Missing program statement and program body"); 1092752Speter #endif OBJ 1093752Speter 1094752Speter } 1095752Speter 1096752Speter 1097752Speter /* 1098752Speter * Level1 does level one processing for 1099752Speter * separately compiled routine segments 1100752Speter */ 1101752Speter level1() 1102752Speter { 1103752Speter 1104752Speter # ifdef OBJ 1105752Speter error("Missing program statement"); 1106752Speter # endif OBJ 1107752Speter # ifdef PC 1108752Speter if (opt('s')) { 1109752Speter standard(); 1110752Speter error("Missing program statement"); 1111752Speter } 1112752Speter # endif PC 1113752Speter 1114752Speter cbn++; 1115752Speter sizes[cbn].om_max = sizes[cbn].om_off = -DPOFF1; 1116834Speter gotos[cbn] = NIL; 1117834Speter errcnt[cbn] = syneflg; 1118834Speter parts[ cbn ] = NIL; 1119834Speter dfiles[ cbn ] = FALSE; 1120*3073Smckusic progseen = TRUE; 1121752Speter } 1122752Speter 1123752Speter 1124752Speter 1125752Speter pnums(p) 1126752Speter struct udinfo *p; 1127752Speter { 1128752Speter 1129752Speter if (p->ud_next != NIL) 1130752Speter pnums(p->ud_next); 1131752Speter if (pnumcnt == 0) { 1132752Speter printf("\n\t"); 1133752Speter pnumcnt = 20; 1134752Speter } 1135752Speter pnumcnt--; 1136752Speter printf(" %d", p->ud_line); 1137752Speter } 1138752Speter 1139752Speter nerror(a1, a2, a3) 1140752Speter { 1141752Speter 1142752Speter if (Fp != NIL) { 1143752Speter yySsync(); 1144752Speter #ifndef PI1 1145752Speter if (opt('l')) 1146752Speter yyoutline(); 1147752Speter #endif 1148752Speter yysetfile(filename); 1149752Speter printf("In %s %s:\n", classes[Fp->class], Fp->symbol); 1150752Speter Fp = NIL; 1151752Speter elineoff(); 1152752Speter } 1153752Speter error(a1, a2, a3); 1154752Speter } 1155