1*3192Smckusick /* Copyright (c) 1979 Regents of the University of California */ 2*3192Smckusick 3*3192Smckusick static char sccsid[] = "@(#)fend.c 1.1 03/11/81"; 4*3192Smckusick 5*3192Smckusick #include "whoami.h" 6*3192Smckusick #include "0.h" 7*3192Smckusick #include "tree.h" 8*3192Smckusick #include "opcode.h" 9*3192Smckusick #include "objfmt.h" 10*3192Smckusick #include "align.h" 11*3192Smckusick 12*3192Smckusick /* 13*3192Smckusick * this array keeps the pxp counters associated with 14*3192Smckusick * functions and procedures, so that they can be output 15*3192Smckusick * when their bodies are encountered 16*3192Smckusick */ 17*3192Smckusick int bodycnts[ DSPLYSZ ]; 18*3192Smckusick 19*3192Smckusick #ifdef PC 20*3192Smckusick # include "pc.h" 21*3192Smckusick # include "pcops.h" 22*3192Smckusick #endif PC 23*3192Smckusick 24*3192Smckusick #ifdef OBJ 25*3192Smckusick int cntpatch; 26*3192Smckusick int nfppatch; 27*3192Smckusick #endif OBJ 28*3192Smckusick 29*3192Smckusick struct nl *Fp; 30*3192Smckusick int pnumcnt; 31*3192Smckusick /* 32*3192Smckusick * Funcend is called to 33*3192Smckusick * finish a block by generating 34*3192Smckusick * the code for the statements. 35*3192Smckusick * It then looks for unresolved declarations 36*3192Smckusick * of labels, procedures and functions, 37*3192Smckusick * and cleans up the name list. 38*3192Smckusick * For the program, it checks the 39*3192Smckusick * semantics of the program 40*3192Smckusick * statement (yuchh). 41*3192Smckusick */ 42*3192Smckusick funcend(fp, bundle, endline) 43*3192Smckusick struct nl *fp; 44*3192Smckusick int *bundle; 45*3192Smckusick int endline; 46*3192Smckusick { 47*3192Smckusick register struct nl *p; 48*3192Smckusick register int i, b; 49*3192Smckusick int var, inp, out, *blk; 50*3192Smckusick bool chkref; 51*3192Smckusick struct nl *iop; 52*3192Smckusick char *cp; 53*3192Smckusick extern int cntstat; 54*3192Smckusick # ifdef PC 55*3192Smckusick int toplabel = getlab(); 56*3192Smckusick int botlabel = getlab(); 57*3192Smckusick # endif PC 58*3192Smckusick 59*3192Smckusick cntstat = 0; 60*3192Smckusick /* 61*3192Smckusick * yyoutline(); 62*3192Smckusick */ 63*3192Smckusick if (program != NIL) 64*3192Smckusick line = program->value[3]; 65*3192Smckusick blk = bundle[2]; 66*3192Smckusick if (fp == NIL) { 67*3192Smckusick cbn--; 68*3192Smckusick # ifdef PTREE 69*3192Smckusick nesting--; 70*3192Smckusick # endif PTREE 71*3192Smckusick return; 72*3192Smckusick } 73*3192Smckusick #ifdef OBJ 74*3192Smckusick /* 75*3192Smckusick * Patch the branch to the 76*3192Smckusick * entry point of the function 77*3192Smckusick */ 78*3192Smckusick patch4(fp->entloc); 79*3192Smckusick /* 80*3192Smckusick * Put out the block entrance code and the block name. 81*3192Smckusick * HDRSZE is the number of bytes of info in the static 82*3192Smckusick * BEG data area exclusive of the proc name. It is 83*3192Smckusick * currently defined as: 84*3192Smckusick /* struct hdr { 85*3192Smckusick /* long framesze; /* number of bytes of local vars */ 86*3192Smckusick /* long nargs; /* number of bytes of arguments */ 87*3192Smckusick /* bool tests; /* TRUE => perform runtime tests */ 88*3192Smckusick /* short offset; /* offset of procedure in source file */ 89*3192Smckusick /* char name[1]; /* name of active procedure */ 90*3192Smckusick /* }; 91*3192Smckusick */ 92*3192Smckusick # define HDRSZE (2 * sizeof(long) + sizeof(short) + sizeof(bool)) 93*3192Smckusick var = put(2, ((lenstr(fp->symbol,0) + HDRSZE) << 8) 94*3192Smckusick | (cbn == 1 && opt('p') == 0 ? O_NODUMP: O_BEG), (long)0); 95*3192Smckusick /* 96*3192Smckusick * output the number of bytes of arguments 97*3192Smckusick * this is only checked on formal calls. 98*3192Smckusick */ 99*3192Smckusick put(2, O_CASE4, cbn == 1 ? (long)0 : (long)(fp->value[NL_OFFS]-DPOFF2)); 100*3192Smckusick /* 101*3192Smckusick * Output the runtime test mode for the routine 102*3192Smckusick */ 103*3192Smckusick put(2, sizeof(bool) == 2 ? O_CASE2 : O_CASE4, opt('t') ? TRUE : FALSE); 104*3192Smckusick /* 105*3192Smckusick * Output line number and routine name 106*3192Smckusick */ 107*3192Smckusick put(2, O_CASE2, bundle[1]); 108*3192Smckusick putstr(fp->symbol, 0); 109*3192Smckusick #endif OBJ 110*3192Smckusick #ifdef PC 111*3192Smckusick /* 112*3192Smckusick * put out the procedure entry code 113*3192Smckusick */ 114*3192Smckusick if ( fp -> class == PROG ) { 115*3192Smckusick putprintf( " .text" , 0 ); 116*3192Smckusick putprintf( " .align 1" , 0 ); 117*3192Smckusick putprintf( " .globl _main" , 0 ); 118*3192Smckusick putprintf( "_main:" , 0 ); 119*3192Smckusick putprintf( " .word 0" , 0 ); 120*3192Smckusick putprintf( " calls $0,_PCSTART" , 0 ); 121*3192Smckusick putprintf( " movl 4(ap),__argc" , 0 ); 122*3192Smckusick putprintf( " movl 8(ap),__argv" , 0 ); 123*3192Smckusick putprintf( " calls $0,_program" , 0 ); 124*3192Smckusick putprintf( " calls $0,_PCEXIT" , 0 ); 125*3192Smckusick ftnno = fp -> entloc; 126*3192Smckusick putprintf( " .text" , 0 ); 127*3192Smckusick putprintf( " .align 1" , 0 ); 128*3192Smckusick putprintf( " .globl _program" , 0 ); 129*3192Smckusick putprintf( "_program:" , 0 ); 130*3192Smckusick stabfunc( "program" , fp -> class , bundle[1] , 0 ); 131*3192Smckusick } else { 132*3192Smckusick ftnno = fp -> entloc; 133*3192Smckusick putprintf( " .text" , 0 ); 134*3192Smckusick putprintf( " .align 1" , 0 ); 135*3192Smckusick putprintf( " .globl " , 1 ); 136*3192Smckusick for ( i = 1 ; i < cbn ; i++ ) { 137*3192Smckusick putprintf( EXTFORMAT , 1 , enclosing[ i ] ); 138*3192Smckusick } 139*3192Smckusick putprintf( "" , 0 ); 140*3192Smckusick for ( i = 1 ; i < cbn ; i++ ) { 141*3192Smckusick putprintf( EXTFORMAT , 1 , enclosing[ i ] ); 142*3192Smckusick } 143*3192Smckusick putprintf( ":" , 0 ); 144*3192Smckusick stabfunc( fp -> symbol , fp -> class , bundle[1] , cbn - 1 ); 145*3192Smckusick for ( p = fp -> chain ; p != NIL ; p = p -> chain ) { 146*3192Smckusick stabparam( p -> symbol , p2type( p -> type ) 147*3192Smckusick , p -> value[ NL_OFFS ] , lwidth( p -> type ) ); 148*3192Smckusick } 149*3192Smckusick if ( fp -> class == FUNC ) { 150*3192Smckusick /* 151*3192Smckusick * stab the function variable 152*3192Smckusick */ 153*3192Smckusick p = fp -> ptr[ NL_FVAR ]; 154*3192Smckusick stablvar( p -> symbol , p2type( p -> type ) , cbn 155*3192Smckusick , p -> value[ NL_OFFS ] , lwidth( p -> type ) ); 156*3192Smckusick } 157*3192Smckusick /* 158*3192Smckusick * stab local variables 159*3192Smckusick * rummage down hash chain links. 160*3192Smckusick */ 161*3192Smckusick for ( i = 0 ; i <= 077 ; i++ ) { 162*3192Smckusick for ( p = disptab[ i ] ; p != NIL ; p = p->nl_next) { 163*3192Smckusick if ( ( p -> nl_block & 037 ) != cbn ) { 164*3192Smckusick break; 165*3192Smckusick } 166*3192Smckusick /* 167*3192Smckusick * stab local variables 168*3192Smckusick * that's named variables, but not params 169*3192Smckusick */ 170*3192Smckusick if ( ( p -> symbol != NIL ) 171*3192Smckusick && ( p -> class == VAR ) 172*3192Smckusick && ( p -> value[ NL_OFFS ] < 0 ) ) { 173*3192Smckusick stablvar( p -> symbol , p2type( p -> type ) , cbn 174*3192Smckusick , p -> value[ NL_OFFS ] , lwidth( p -> type ) ); 175*3192Smckusick } 176*3192Smckusick } 177*3192Smckusick } 178*3192Smckusick } 179*3192Smckusick stablbrac( cbn ); 180*3192Smckusick /* 181*3192Smckusick * register save mask 182*3192Smckusick */ 183*3192Smckusick if ( opt( 't' ) ) { 184*3192Smckusick putprintf( " .word 0x%x" , 0 , RUNCHECK | RSAVEMASK ); 185*3192Smckusick } else { 186*3192Smckusick putprintf( " .word 0x%x" , 0 , RSAVEMASK ); 187*3192Smckusick } 188*3192Smckusick putjbr( botlabel ); 189*3192Smckusick putlab( toplabel ); 190*3192Smckusick if ( profflag ) { 191*3192Smckusick /* 192*3192Smckusick * call mcount for profiling 193*3192Smckusick */ 194*3192Smckusick putprintf( " moval 1f,r0" , 0 ); 195*3192Smckusick putprintf( " jsb mcount" , 0 ); 196*3192Smckusick putprintf( " .data" , 0 ); 197*3192Smckusick putprintf( " .align 2" , 0 ); 198*3192Smckusick putprintf( "1:" , 0 ); 199*3192Smckusick putprintf( " .long 0" , 0 ); 200*3192Smckusick putprintf( " .text" , 0 ); 201*3192Smckusick } 202*3192Smckusick /* 203*3192Smckusick * set up unwind exception vector. 204*3192Smckusick */ 205*3192Smckusick putprintf( " moval %s,%d(%s)" , 0 206*3192Smckusick , UNWINDNAME , UNWINDOFFSET , P2FPNAME ); 207*3192Smckusick /* 208*3192Smckusick * save address of display entry, for unwind. 209*3192Smckusick */ 210*3192Smckusick putprintf( " moval %s+%d,%d(%s)" , 0 211*3192Smckusick , DISPLAYNAME , cbn * sizeof(struct dispsave) 212*3192Smckusick , DPTROFFSET , P2FPNAME ); 213*3192Smckusick /* 214*3192Smckusick * save old display 215*3192Smckusick */ 216*3192Smckusick putprintf( " movq %s+%d,%d(%s)" , 0 217*3192Smckusick , DISPLAYNAME , cbn * sizeof(struct dispsave) 218*3192Smckusick , DSAVEOFFSET , P2FPNAME ); 219*3192Smckusick /* 220*3192Smckusick * set up new display by saving AP and FP in appropriate 221*3192Smckusick * slot in display structure. 222*3192Smckusick */ 223*3192Smckusick putprintf( " movq %s,%s+%d" , 0 224*3192Smckusick , P2APNAME , DISPLAYNAME , cbn * sizeof(struct dispsave) ); 225*3192Smckusick /* 226*3192Smckusick * ask second pass to allocate known locals 227*3192Smckusick */ 228*3192Smckusick putlbracket( ftnno , -sizes[ cbn ].om_max ); 229*3192Smckusick /* 230*3192Smckusick * and zero them if checking is on 231*3192Smckusick * by calling blkclr( bytes of locals , starting local address ); 232*3192Smckusick */ 233*3192Smckusick if ( opt( 't' ) ) { 234*3192Smckusick if ( ( -sizes[ cbn ].om_max ) > DPOFF1 ) { 235*3192Smckusick putleaf( P2ICON , 0 , 0 , ADDTYPE( P2FTN | P2INT , P2PTR ) 236*3192Smckusick , "_blkclr" ); 237*3192Smckusick putleaf( P2ICON , ( -sizes[ cbn ].om_max ) - DPOFF1 238*3192Smckusick , 0 , P2INT , 0 ); 239*3192Smckusick putLV( 0 , cbn , sizes[ cbn ].om_max , P2CHAR ); 240*3192Smckusick putop( P2LISTOP , P2INT ); 241*3192Smckusick putop( P2CALL , P2INT ); 242*3192Smckusick putdot( filename , line ); 243*3192Smckusick } 244*3192Smckusick /* 245*3192Smckusick * check number of longs of arguments 246*3192Smckusick * this can only be wrong for formal calls. 247*3192Smckusick */ 248*3192Smckusick if ( fp -> class != PROG ) { 249*3192Smckusick putleaf( P2ICON , 0 , 0 , ADDTYPE( P2PTR , P2FTN | P2INT ) , 250*3192Smckusick "_NARGCHK" ); 251*3192Smckusick putleaf( P2ICON , 252*3192Smckusick (fp->value[NL_OFFS] - DPOFF2) / sizeof(long) , 253*3192Smckusick 0 , P2INT , 0 ); 254*3192Smckusick putop( P2CALL , P2INT ); 255*3192Smckusick putdot( filename , line ); 256*3192Smckusick } 257*3192Smckusick } 258*3192Smckusick #endif PC 259*3192Smckusick if ( monflg ) { 260*3192Smckusick if ( fp -> value[ NL_CNTR ] != 0 ) { 261*3192Smckusick inccnt( fp -> value [ NL_CNTR ] ); 262*3192Smckusick } 263*3192Smckusick inccnt( bodycnts[ fp -> nl_block & 037 ] ); 264*3192Smckusick } 265*3192Smckusick if (fp->class == PROG) { 266*3192Smckusick /* 267*3192Smckusick * The glorious buffers option. 268*3192Smckusick * 0 = don't buffer output 269*3192Smckusick * 1 = line buffer output 270*3192Smckusick * 2 = 512 byte buffer output 271*3192Smckusick */ 272*3192Smckusick # ifdef OBJ 273*3192Smckusick if (opt('b') != 1) 274*3192Smckusick put(1, O_BUFF | opt('b') << 8); 275*3192Smckusick # endif OBJ 276*3192Smckusick # ifdef PC 277*3192Smckusick if ( opt( 'b' ) != 1 ) { 278*3192Smckusick putleaf( P2ICON , 0 , 0 279*3192Smckusick , ADDTYPE( P2FTN | P2INT , P2PTR ) , "_BUFF" ); 280*3192Smckusick putleaf( P2ICON , opt( 'b' ) , 0 , P2INT , 0 ); 281*3192Smckusick putop( P2CALL , P2INT ); 282*3192Smckusick putdot( filename , line ); 283*3192Smckusick } 284*3192Smckusick # endif PC 285*3192Smckusick out = 0; 286*3192Smckusick for (p = fp->chain; p != NIL; p = p->chain) { 287*3192Smckusick if (strcmp(p->symbol, "input") == 0) { 288*3192Smckusick inp++; 289*3192Smckusick continue; 290*3192Smckusick } 291*3192Smckusick if (strcmp(p->symbol, "output") == 0) { 292*3192Smckusick out++; 293*3192Smckusick continue; 294*3192Smckusick } 295*3192Smckusick iop = lookup1(p->symbol); 296*3192Smckusick if (iop == NIL || bn != cbn) { 297*3192Smckusick error("File %s listed in program statement but not declared", p->symbol); 298*3192Smckusick continue; 299*3192Smckusick } 300*3192Smckusick if (iop->class != VAR) { 301*3192Smckusick error("File %s listed in program statement but declared as a %s", p->symbol, classes[iop->class]); 302*3192Smckusick continue; 303*3192Smckusick } 304*3192Smckusick if (iop->type == NIL) 305*3192Smckusick continue; 306*3192Smckusick if (iop->type->class != FILET) { 307*3192Smckusick error("File %s listed in program statement but defined as %s", 308*3192Smckusick p->symbol, nameof(iop->type)); 309*3192Smckusick continue; 310*3192Smckusick } 311*3192Smckusick # ifdef OBJ 312*3192Smckusick put(2, O_CON24, text(iop->type) ? 0 : width(iop->type->type)); 313*3192Smckusick i = lenstr(p->symbol,0); 314*3192Smckusick put(2, O_CON24, i); 315*3192Smckusick put(2, O_LVCON, i); 316*3192Smckusick putstr(p->symbol, 0); 317*3192Smckusick put(2, O_LV | bn<<8+INDX, (int)iop->value[NL_OFFS]); 318*3192Smckusick put(1, O_DEFNAME); 319*3192Smckusick # endif OBJ 320*3192Smckusick # ifdef PC 321*3192Smckusick putleaf( P2ICON , 0 , 0 322*3192Smckusick , ADDTYPE( P2FTN | P2INT , P2PTR ) 323*3192Smckusick , "_DEFNAME" ); 324*3192Smckusick putLV( p -> symbol , bn , iop -> value[NL_OFFS] 325*3192Smckusick , p2type( iop ) ); 326*3192Smckusick putCONG( p -> symbol , strlen( p -> symbol ) 327*3192Smckusick , LREQ ); 328*3192Smckusick putop( P2LISTOP , P2INT ); 329*3192Smckusick putleaf( P2ICON , strlen( p -> symbol ) 330*3192Smckusick , 0 , P2INT , 0 ); 331*3192Smckusick putop( P2LISTOP , P2INT ); 332*3192Smckusick putleaf( P2ICON 333*3192Smckusick , text(iop->type) ? 0 : width(iop->type->type) 334*3192Smckusick , 0 , P2INT , 0 ); 335*3192Smckusick putop( P2LISTOP , P2INT ); 336*3192Smckusick putop( P2CALL , P2INT ); 337*3192Smckusick putdot( filename , line ); 338*3192Smckusick # endif PC 339*3192Smckusick } 340*3192Smckusick if (out == 0 && fp->chain != NIL) { 341*3192Smckusick recovered(); 342*3192Smckusick error("The file output must appear in the program statement file list"); 343*3192Smckusick } 344*3192Smckusick } 345*3192Smckusick /* 346*3192Smckusick * Process the prog/proc/func body 347*3192Smckusick */ 348*3192Smckusick noreach = 0; 349*3192Smckusick line = bundle[1]; 350*3192Smckusick statlist(blk); 351*3192Smckusick # ifdef PTREE 352*3192Smckusick { 353*3192Smckusick pPointer Body = tCopy( blk ); 354*3192Smckusick 355*3192Smckusick pDEF( PorFHeader[ nesting -- ] ).PorFBody = Body; 356*3192Smckusick } 357*3192Smckusick # endif PTREE 358*3192Smckusick # ifdef OBJ 359*3192Smckusick if (cbn== 1 && monflg != 0) { 360*3192Smckusick patchfil(cntpatch - 2, (long)cnts, 2); 361*3192Smckusick patchfil(nfppatch - 2, (long)pfcnt, 2); 362*3192Smckusick } 363*3192Smckusick # endif OBJ 364*3192Smckusick # ifdef PC 365*3192Smckusick if ( fp -> class == PROG && monflg ) { 366*3192Smckusick putleaf( P2ICON , 0 , 0 , ADDTYPE( P2FTN | P2INT , P2PTR ) 367*3192Smckusick , "_PMFLUSH" ); 368*3192Smckusick putleaf( P2ICON , cnts , 0 , P2INT , 0 ); 369*3192Smckusick putleaf( P2ICON , pfcnt , 0 , P2INT , 0 ); 370*3192Smckusick putop( P2LISTOP , P2INT ); 371*3192Smckusick putLV( PCPCOUNT , 0 , 0 , P2INT ); 372*3192Smckusick putop( P2LISTOP , P2INT ); 373*3192Smckusick putop( P2CALL , P2INT ); 374*3192Smckusick putdot( filename , line ); 375*3192Smckusick } 376*3192Smckusick # endif PC 377*3192Smckusick if (fp->class == PROG && inp == 0 && (input->nl_flags & (NUSED|NMOD)) != 0) { 378*3192Smckusick recovered(); 379*3192Smckusick error("Input is used but not defined in the program statement"); 380*3192Smckusick } 381*3192Smckusick /* 382*3192Smckusick * Clean up the symbol table displays and check for unresolves 383*3192Smckusick */ 384*3192Smckusick line = endline; 385*3192Smckusick b = cbn; 386*3192Smckusick Fp = fp; 387*3192Smckusick chkref = syneflg == errcnt[cbn] && opt('w') == 0; 388*3192Smckusick for (i = 0; i <= 077; i++) { 389*3192Smckusick for (p = disptab[i]; p != NIL && (p->nl_block & 037) == b; p = p->nl_next) { 390*3192Smckusick /* 391*3192Smckusick * Check for variables defined 392*3192Smckusick * but not referenced 393*3192Smckusick */ 394*3192Smckusick if (chkref && p->symbol != NIL) 395*3192Smckusick switch (p->class) { 396*3192Smckusick case FIELD: 397*3192Smckusick /* 398*3192Smckusick * If the corresponding record is 399*3192Smckusick * unused, we shouldn't complain about 400*3192Smckusick * the fields. 401*3192Smckusick */ 402*3192Smckusick default: 403*3192Smckusick if ((p->nl_flags & (NUSED|NMOD)) == 0) { 404*3192Smckusick warning(); 405*3192Smckusick nerror("%s %s is neither used nor set", classes[p->class], p->symbol); 406*3192Smckusick break; 407*3192Smckusick } 408*3192Smckusick /* 409*3192Smckusick * If a var parameter is either 410*3192Smckusick * modified or used that is enough. 411*3192Smckusick */ 412*3192Smckusick if (p->class == REF) 413*3192Smckusick continue; 414*3192Smckusick # ifdef OBJ 415*3192Smckusick if ((p->nl_flags & NUSED) == 0) { 416*3192Smckusick warning(); 417*3192Smckusick nerror("%s %s is never used", classes[p->class], p->symbol); 418*3192Smckusick break; 419*3192Smckusick } 420*3192Smckusick # endif OBJ 421*3192Smckusick # ifdef PC 422*3192Smckusick if (((p->nl_flags & NUSED) == 0) && ((p->ext_flags & NEXTERN) == 0)) { 423*3192Smckusick warning(); 424*3192Smckusick nerror("%s %s is never used", classes[p->class], p->symbol); 425*3192Smckusick break; 426*3192Smckusick } 427*3192Smckusick # endif PC 428*3192Smckusick if ((p->nl_flags & NMOD) == 0) { 429*3192Smckusick warning(); 430*3192Smckusick nerror("%s %s is used but never set", classes[p->class], p->symbol); 431*3192Smckusick break; 432*3192Smckusick } 433*3192Smckusick case LABEL: 434*3192Smckusick case FVAR: 435*3192Smckusick case BADUSE: 436*3192Smckusick break; 437*3192Smckusick } 438*3192Smckusick switch (p->class) { 439*3192Smckusick case BADUSE: 440*3192Smckusick cp = "s"; 441*3192Smckusick if (p->chain->ud_next == NIL) 442*3192Smckusick cp++; 443*3192Smckusick eholdnl(); 444*3192Smckusick if (p->value[NL_KINDS] & ISUNDEF) 445*3192Smckusick nerror("%s undefined on line%s", p->symbol, cp); 446*3192Smckusick else 447*3192Smckusick nerror("%s improperly used on line%s", p->symbol, cp); 448*3192Smckusick pnumcnt = 10; 449*3192Smckusick pnums(p->chain); 450*3192Smckusick pchr('\n'); 451*3192Smckusick break; 452*3192Smckusick 453*3192Smckusick case FUNC: 454*3192Smckusick case PROC: 455*3192Smckusick # ifdef OBJ 456*3192Smckusick if ((p->nl_flags & NFORWD)) 457*3192Smckusick nerror("Unresolved forward declaration of %s %s", classes[p->class], p->symbol); 458*3192Smckusick # endif OBJ 459*3192Smckusick # ifdef PC 460*3192Smckusick if ((p->nl_flags & NFORWD) && ((p->ext_flags & NEXTERN) == 0)) 461*3192Smckusick nerror("Unresolved forward declaration of %s %s", classes[p->class], p->symbol); 462*3192Smckusick # endif PC 463*3192Smckusick break; 464*3192Smckusick 465*3192Smckusick case LABEL: 466*3192Smckusick if (p->nl_flags & NFORWD) 467*3192Smckusick nerror("label %s was declared but not defined", p->symbol); 468*3192Smckusick break; 469*3192Smckusick case FVAR: 470*3192Smckusick if ((p->nl_flags & NMOD) == 0) 471*3192Smckusick nerror("No assignment to the function variable"); 472*3192Smckusick break; 473*3192Smckusick } 474*3192Smckusick } 475*3192Smckusick /* 476*3192Smckusick * Pop this symbol 477*3192Smckusick * table slot 478*3192Smckusick */ 479*3192Smckusick disptab[i] = p; 480*3192Smckusick } 481*3192Smckusick 482*3192Smckusick # ifdef OBJ 483*3192Smckusick put(1, O_END); 484*3192Smckusick # endif OBJ 485*3192Smckusick # ifdef PC 486*3192Smckusick /* 487*3192Smckusick * if there were file variables declared at this level 488*3192Smckusick * call pclose( &__disply[ cbn ] ) to clean them up. 489*3192Smckusick */ 490*3192Smckusick if ( dfiles[ cbn ] ) { 491*3192Smckusick putleaf( P2ICON , 0 , 0 , ADDTYPE( P2FTN | P2INT , P2PTR ) 492*3192Smckusick , "_PCLOSE" ); 493*3192Smckusick putRV( DISPLAYNAME , 0 , cbn * sizeof( struct dispsave ) 494*3192Smckusick , P2PTR | P2CHAR ); 495*3192Smckusick putop( P2CALL , P2INT ); 496*3192Smckusick putdot( filename , line ); 497*3192Smckusick } 498*3192Smckusick /* 499*3192Smckusick * if this is a function, 500*3192Smckusick * the function variable is the return value. 501*3192Smckusick * if it's a scalar valued function, return scalar, 502*3192Smckusick * else, return a pointer to the structure value. 503*3192Smckusick */ 504*3192Smckusick if ( fp -> class == FUNC ) { 505*3192Smckusick struct nl *fvar = fp -> ptr[ NL_FVAR ]; 506*3192Smckusick long fvartype = p2type( fvar -> type ); 507*3192Smckusick long label; 508*3192Smckusick char labelname[ BUFSIZ ]; 509*3192Smckusick 510*3192Smckusick switch ( classify( fvar -> type ) ) { 511*3192Smckusick case TBOOL: 512*3192Smckusick case TCHAR: 513*3192Smckusick case TINT: 514*3192Smckusick case TSCAL: 515*3192Smckusick case TDOUBLE: 516*3192Smckusick case TPTR: 517*3192Smckusick putRV( fvar -> symbol , ( fvar -> nl_block ) & 037 518*3192Smckusick , fvar -> value[ NL_OFFS ] , fvartype ); 519*3192Smckusick break; 520*3192Smckusick default: 521*3192Smckusick label = getlab(); 522*3192Smckusick sprintf( labelname , PREFIXFORMAT , 523*3192Smckusick LABELPREFIX , label ); 524*3192Smckusick putprintf( " .data" , 0 ); 525*3192Smckusick putprintf( " .lcomm %s,%d" , 0 , 526*3192Smckusick labelname , lwidth( fvar -> type ) ); 527*3192Smckusick putprintf( " .text" , 0 ); 528*3192Smckusick putleaf( P2NAME , 0 , 0 , fvartype , labelname ); 529*3192Smckusick putLV( fvar -> symbol , ( fvar -> nl_block ) & 037 530*3192Smckusick , fvar -> value[ NL_OFFS ] , fvartype ); 531*3192Smckusick putstrop( P2STASG , fvartype , lwidth( fvar -> type ) , 532*3192Smckusick align( fvar -> type ) ); 533*3192Smckusick putdot( filename , line ); 534*3192Smckusick putleaf( P2ICON , 0 , 0 , fvartype , labelname ); 535*3192Smckusick break; 536*3192Smckusick } 537*3192Smckusick putop( P2FORCE , fvartype ); 538*3192Smckusick putdot( filename , line ); 539*3192Smckusick } 540*3192Smckusick /* 541*3192Smckusick * restore old display entry from save area 542*3192Smckusick */ 543*3192Smckusick 544*3192Smckusick putprintf( " movq %d(%s),%s+%d" , 0 545*3192Smckusick , DSAVEOFFSET , P2FPNAME 546*3192Smckusick , DISPLAYNAME , cbn * sizeof(struct dispsave) ); 547*3192Smckusick stabrbrac( cbn ); 548*3192Smckusick putprintf( " ret" , 0 ); 549*3192Smckusick /* 550*3192Smckusick * let the second pass allocate locals 551*3192Smckusick */ 552*3192Smckusick putlab( botlabel ); 553*3192Smckusick putprintf( " subl2 $LF%d,sp" , 0 , ftnno ); 554*3192Smckusick putrbracket( ftnno ); 555*3192Smckusick putjbr( toplabel ); 556*3192Smckusick /* 557*3192Smckusick * declare pcp counters, if any 558*3192Smckusick */ 559*3192Smckusick if ( monflg && fp -> class == PROG ) { 560*3192Smckusick putprintf( " .data" , 0 ); 561*3192Smckusick putprintf( " .comm " , 1 ); 562*3192Smckusick putprintf( PCPCOUNT , 1 ); 563*3192Smckusick putprintf( ",%d" , 0 , ( cnts + 1 ) * sizeof (long) ); 564*3192Smckusick putprintf( " .text" , 0 ); 565*3192Smckusick } 566*3192Smckusick # endif PC 567*3192Smckusick #ifdef DEBUG 568*3192Smckusick dumpnl(fp->ptr[2], fp->symbol); 569*3192Smckusick #endif 570*3192Smckusick /* 571*3192Smckusick * Restore the 572*3192Smckusick * (virtual) name list 573*3192Smckusick * position 574*3192Smckusick */ 575*3192Smckusick nlfree(fp->ptr[2]); 576*3192Smckusick /* 577*3192Smckusick * Proc/func has been 578*3192Smckusick * resolved 579*3192Smckusick */ 580*3192Smckusick fp->nl_flags &= ~NFORWD; 581*3192Smckusick /* 582*3192Smckusick * Patch the beg 583*3192Smckusick * of the proc/func to 584*3192Smckusick * the proper variable size 585*3192Smckusick */ 586*3192Smckusick if (Fp == NIL) 587*3192Smckusick elineon(); 588*3192Smckusick # ifdef OBJ 589*3192Smckusick patchfil(var, (long)(-sizes[cbn].om_max), 2); 590*3192Smckusick # endif OBJ 591*3192Smckusick cbn--; 592*3192Smckusick if (inpflist(fp->symbol)) { 593*3192Smckusick opop('l'); 594*3192Smckusick } 595*3192Smckusick } 596