13192Smckusick /* Copyright (c) 1979 Regents of the University of California */ 23192Smckusick 3*9129Smckusick static char sccsid[] = "@(#)fend.c 1.16 11/12/82"; 43192Smckusick 53192Smckusick #include "whoami.h" 63192Smckusick #include "0.h" 73192Smckusick #include "tree.h" 83192Smckusick #include "opcode.h" 93192Smckusick #include "objfmt.h" 103192Smckusick #include "align.h" 113192Smckusick 123192Smckusick /* 133192Smckusick * this array keeps the pxp counters associated with 143192Smckusick * functions and procedures, so that they can be output 153192Smckusick * when their bodies are encountered 163192Smckusick */ 173192Smckusick int bodycnts[ DSPLYSZ ]; 183192Smckusick 193192Smckusick #ifdef PC 203192Smckusick # include "pc.h" 213192Smckusick # include "pcops.h" 223192Smckusick #endif PC 233192Smckusick 243192Smckusick #ifdef OBJ 253192Smckusick int cntpatch; 263192Smckusick int nfppatch; 273192Smckusick #endif OBJ 283192Smckusick 293192Smckusick struct nl *Fp; 303192Smckusick int pnumcnt; 313192Smckusick /* 323192Smckusick * Funcend is called to 333192Smckusick * finish a block by generating 343192Smckusick * the code for the statements. 353192Smckusick * It then looks for unresolved declarations 363192Smckusick * of labels, procedures and functions, 373192Smckusick * and cleans up the name list. 383192Smckusick * For the program, it checks the 393192Smckusick * semantics of the program 403192Smckusick * statement (yuchh). 413192Smckusick */ 423192Smckusick funcend(fp, bundle, endline) 433192Smckusick struct nl *fp; 443192Smckusick int *bundle; 453192Smckusick int endline; 463192Smckusick { 473192Smckusick register struct nl *p; 483192Smckusick register int i, b; 493192Smckusick int var, inp, out, *blk; 503192Smckusick bool chkref; 513192Smckusick struct nl *iop; 523192Smckusick char *cp; 533192Smckusick extern int cntstat; 543192Smckusick # ifdef PC 553363Speter int savlabel = getlab(); 563363Speter int toplabel = getlab(); 573649Speter int proflabel = getlab(); 589121Smckusick int skip = getlab(); 593363Speter char extname[ BUFSIZ ]; 603192Smckusick # endif PC 613192Smckusick 623192Smckusick cntstat = 0; 633192Smckusick /* 643192Smckusick * yyoutline(); 653192Smckusick */ 663192Smckusick if (program != NIL) 673192Smckusick line = program->value[3]; 683192Smckusick blk = bundle[2]; 693192Smckusick if (fp == NIL) { 703192Smckusick cbn--; 713192Smckusick # ifdef PTREE 723192Smckusick nesting--; 733192Smckusick # endif PTREE 743192Smckusick return; 753192Smckusick } 763192Smckusick #ifdef OBJ 773192Smckusick /* 783192Smckusick * Patch the branch to the 793192Smckusick * entry point of the function 803192Smckusick */ 817917Smckusick patch4(fp->value[NL_ENTLOC]); 823192Smckusick /* 833192Smckusick * Put out the block entrance code and the block name. 843192Smckusick * HDRSZE is the number of bytes of info in the static 853192Smckusick * BEG data area exclusive of the proc name. It is 863192Smckusick * currently defined as: 873192Smckusick /* struct hdr { 883192Smckusick /* long framesze; /* number of bytes of local vars */ 893192Smckusick /* long nargs; /* number of bytes of arguments */ 903192Smckusick /* bool tests; /* TRUE => perform runtime tests */ 913192Smckusick /* short offset; /* offset of procedure in source file */ 923192Smckusick /* char name[1]; /* name of active procedure */ 933192Smckusick /* }; 943192Smckusick */ 953192Smckusick # define HDRSZE (2 * sizeof(long) + sizeof(short) + sizeof(bool)) 963192Smckusick var = put(2, ((lenstr(fp->symbol,0) + HDRSZE) << 8) 973192Smckusick | (cbn == 1 && opt('p') == 0 ? O_NODUMP: O_BEG), (long)0); 983192Smckusick /* 993192Smckusick * output the number of bytes of arguments 1003192Smckusick * this is only checked on formal calls. 1013192Smckusick */ 1023192Smckusick put(2, O_CASE4, cbn == 1 ? (long)0 : (long)(fp->value[NL_OFFS]-DPOFF2)); 1033192Smckusick /* 1043192Smckusick * Output the runtime test mode for the routine 1053192Smckusick */ 1063192Smckusick put(2, sizeof(bool) == 2 ? O_CASE2 : O_CASE4, opt('t') ? TRUE : FALSE); 1073192Smckusick /* 1083192Smckusick * Output line number and routine name 1093192Smckusick */ 1103192Smckusick put(2, O_CASE2, bundle[1]); 1113192Smckusick putstr(fp->symbol, 0); 1123192Smckusick #endif OBJ 1133192Smckusick #ifdef PC 1143192Smckusick /* 1153192Smckusick * put out the procedure entry code 1163192Smckusick */ 1173192Smckusick if ( fp -> class == PROG ) { 118*9129Smckusick /* 119*9129Smckusick * If there is a label declaration in the main routine 120*9129Smckusick * then there may be a non-local goto to it that does 121*9129Smckusick * not appear in this module. We have to assume that 122*9129Smckusick * such a reference may occur and generate code to 123*9129Smckusick * prepare for it. 124*9129Smckusick */ 125*9129Smckusick if ( parts[ cbn ] & LPRT ) { 126*9129Smckusick parts[ cbn ] |= ( NONLOCALVAR | NONLOCALGOTO ); 127*9129Smckusick } 1283192Smckusick putprintf( " .text" , 0 ); 1293192Smckusick putprintf( " .align 1" , 0 ); 1303192Smckusick putprintf( " .globl _main" , 0 ); 1313192Smckusick putprintf( "_main:" , 0 ); 1323192Smckusick putprintf( " .word 0" , 0 ); 1335677Smckusic if ( opt ( 't' ) ) { 1345677Smckusic putprintf( " pushl $1" , 0 ); 1355677Smckusic } else { 1365677Smckusic putprintf( " pushl $0" , 0 ); 1375677Smckusic } 1385677Smckusic putprintf( " calls $1,_PCSTART" , 0 ); 1393192Smckusick putprintf( " movl 4(ap),__argc" , 0 ); 1403192Smckusick putprintf( " movl 8(ap),__argv" , 0 ); 1413192Smckusick putprintf( " calls $0,_program" , 0 ); 1427646Speter putprintf( " pushl $0" , 0 ); 1437646Speter putprintf( " calls $1,_PCEXIT" , 0 ); 1447917Smckusick ftnno = fp -> value[NL_ENTLOC]; 1453192Smckusick putprintf( " .text" , 0 ); 1463192Smckusick putprintf( " .align 1" , 0 ); 1473192Smckusick putprintf( " .globl _program" , 0 ); 1483192Smckusick putprintf( "_program:" , 0 ); 1493192Smckusick stabfunc( "program" , fp -> class , bundle[1] , 0 ); 1503192Smckusick } else { 1517917Smckusick ftnno = fp -> value[NL_ENTLOC]; 1523192Smckusick putprintf( " .text" , 0 ); 1533192Smckusick putprintf( " .align 1" , 0 ); 1543367Speter sextname( extname , fp -> symbol , cbn - 1 ); 1553428Speter putprintf( " .globl %s%s" , 0 , FORMALPREFIX , extname ); 1563363Speter putprintf( " .globl %s" , 0 , extname ); 1573363Speter putprintf( "%s:" , 0 , extname ); 1583192Smckusick stabfunc( fp -> symbol , fp -> class , bundle[1] , cbn - 1 ); 1593192Smckusick for ( p = fp -> chain ; p != NIL ; p = p -> chain ) { 1603192Smckusick stabparam( p -> symbol , p2type( p -> type ) 1613192Smckusick , p -> value[ NL_OFFS ] , lwidth( p -> type ) ); 1623192Smckusick } 1633192Smckusick if ( fp -> class == FUNC ) { 1643192Smckusick /* 1653192Smckusick * stab the function variable 1663192Smckusick */ 1673192Smckusick p = fp -> ptr[ NL_FVAR ]; 1683192Smckusick stablvar( p -> symbol , p2type( p -> type ) , cbn 1693192Smckusick , p -> value[ NL_OFFS ] , lwidth( p -> type ) ); 1703192Smckusick } 1713192Smckusick /* 1723192Smckusick * stab local variables 1733192Smckusick * rummage down hash chain links. 1743192Smckusick */ 1753192Smckusick for ( i = 0 ; i <= 077 ; i++ ) { 1763192Smckusick for ( p = disptab[ i ] ; p != NIL ; p = p->nl_next) { 1773192Smckusick if ( ( p -> nl_block & 037 ) != cbn ) { 1783192Smckusick break; 1793192Smckusick } 1803192Smckusick /* 1813192Smckusick * stab local variables 1823192Smckusick * that's named variables, but not params 1833192Smckusick */ 1843192Smckusick if ( ( p -> symbol != NIL ) 1853192Smckusick && ( p -> class == VAR ) 1863192Smckusick && ( p -> value[ NL_OFFS ] < 0 ) ) { 1873192Smckusick stablvar( p -> symbol , p2type( p -> type ) , cbn 1883192Smckusick , p -> value[ NL_OFFS ] , lwidth( p -> type ) ); 1893192Smckusick } 1903192Smckusick } 1913192Smckusick } 1923192Smckusick } 1933192Smckusick stablbrac( cbn ); 1943192Smckusick /* 1953192Smckusick * register save mask 1963192Smckusick */ 1973279Smckusic putprintf( " .word " , 1 ); 1983279Smckusic putprintf( PREFIXFORMAT , 0 , LABELPREFIX , savlabel ); 1993192Smckusick putlab( toplabel ); 2009127Smckusick putprintf( " subl2 $LF%d,sp" , 0 , ftnno ); 2013192Smckusick if ( profflag ) { 2023192Smckusick /* 2033192Smckusick * call mcount for profiling 2043192Smckusick */ 2053649Speter putprintf( " moval " , 1 ); 2063649Speter putprintf( PREFIXFORMAT , 1 , LABELPREFIX , proflabel ); 2073649Speter putprintf( ",r0" , 0 ); 2083192Smckusick putprintf( " jsb mcount" , 0 ); 2093192Smckusick putprintf( " .data" , 0 ); 2103192Smckusick putprintf( " .align 2" , 0 ); 2113649Speter putlab( proflabel ); 2123192Smckusick putprintf( " .long 0" , 0 ); 2133192Smckusick putprintf( " .text" , 0 ); 2143192Smckusick } 2153192Smckusick /* 216*9129Smckusick * if there are nested procedures that access our variables 217*9129Smckusick * we must save the display. 2183192Smckusick */ 2199127Smckusick if ( parts[ cbn ] & NONLOCALVAR ) { 2209127Smckusick /* 2219127Smckusick * save old display 2229127Smckusick */ 2239127Smckusick putprintf( " movq %s+%d,%d(%s)" , 0 2249127Smckusick , DISPLAYNAME , cbn * sizeof(struct dispsave) 2259127Smckusick , DSAVEOFFSET , P2FPNAME ); 2269127Smckusick /* 2279127Smckusick * set up new display by saving AP and FP in appropriate 2289127Smckusick * slot in display structure. 2299127Smckusick */ 2309127Smckusick putprintf( " movq %s,%s+%d" , 0 2319127Smckusick , P2APNAME , DISPLAYNAME , cbn * sizeof(struct dispsave) ); 2329127Smckusick } 2333192Smckusick /* 2345677Smckusic * set underflow checking if runtime tests 2355677Smckusic */ 2365677Smckusic if ( opt( 't' ) ) { 2375677Smckusic putprintf( " bispsw $0xe0" , 0 ); 2385677Smckusic } 2395677Smckusic /* 2403192Smckusick * ask second pass to allocate known locals 2413192Smckusick */ 2423192Smckusick putlbracket( ftnno , -sizes[ cbn ].om_max ); 2433192Smckusick /* 2443192Smckusick * and zero them if checking is on 2453192Smckusick * by calling blkclr( bytes of locals , starting local address ); 2463192Smckusick */ 2473301Smckusic if ( opt( 't' ) && ( -sizes[ cbn ].om_max ) > DPOFF1 ) { 2483301Smckusic putleaf( P2ICON , 0 , 0 , ADDTYPE( P2FTN | P2INT , P2PTR ) 2493301Smckusic , "_blkclr" ); 2503301Smckusic putleaf( P2ICON , ( -sizes[ cbn ].om_max ) - DPOFF1 2513301Smckusic , 0 , P2INT , 0 ); 2523837Speter putLV( 0 , cbn , sizes[ cbn ].om_max , NLOCAL , P2CHAR ); 2533301Smckusic putop( P2LISTOP , P2INT ); 2543301Smckusic putop( P2CALL , P2INT ); 2553301Smckusic putdot( filename , line ); 2563192Smckusick } 2579121Smckusick /* 258*9129Smckusick * set up goto vector if non-local goto to this frame 2599121Smckusick */ 260*9129Smckusick if ( parts[ cbn ] & NONLOCALGOTO ) { 2619127Smckusick putleaf( P2ICON , 0 , 0 , ADDTYPE( P2FTN | P2INT , P2PTR ) 2629127Smckusick , "_setjmp" ); 2639127Smckusick putLV( 0 , cbn , GOTOENVOFFSET , NLOCAL , P2PTR|P2STRTY ); 2649127Smckusick putop( P2CALL , P2INT ); 2659127Smckusick putleaf( P2ICON , 0 , 0 , P2INT , 0 ); 2669127Smckusick putop( P2NE , P2INT ); 2679127Smckusick putleaf( P2ICON , skip , 0 , P2INT , 0 ); 2689127Smckusick putop( P2CBRANCH , P2INT ); 2699127Smckusick putdot( filename , line ); 2709127Smckusick /* 2719127Smckusick * on non-local goto, setjmp returns with address to 2729127Smckusick * be branched to. 2739127Smckusick */ 2749127Smckusick putprintf( " jmp (r0)" , 0 ); 2759127Smckusick putlab(skip); 2769127Smckusick } 2773192Smckusick #endif PC 2783192Smckusick if ( monflg ) { 2793192Smckusick if ( fp -> value[ NL_CNTR ] != 0 ) { 2803192Smckusick inccnt( fp -> value [ NL_CNTR ] ); 2813192Smckusick } 2823192Smckusick inccnt( bodycnts[ fp -> nl_block & 037 ] ); 2833192Smckusick } 2843192Smckusick if (fp->class == PROG) { 2853192Smckusick /* 2863192Smckusick * The glorious buffers option. 2873192Smckusick * 0 = don't buffer output 2883192Smckusick * 1 = line buffer output 2893192Smckusick * 2 = 512 byte buffer output 2903192Smckusick */ 2913192Smckusick # ifdef OBJ 2923192Smckusick if (opt('b') != 1) 2933192Smckusick put(1, O_BUFF | opt('b') << 8); 2943192Smckusick # endif OBJ 2953192Smckusick # ifdef PC 2963192Smckusick if ( opt( 'b' ) != 1 ) { 2973192Smckusick putleaf( P2ICON , 0 , 0 2983192Smckusick , ADDTYPE( P2FTN | P2INT , P2PTR ) , "_BUFF" ); 2993192Smckusick putleaf( P2ICON , opt( 'b' ) , 0 , P2INT , 0 ); 3003192Smckusick putop( P2CALL , P2INT ); 3013192Smckusick putdot( filename , line ); 3023192Smckusick } 3033192Smckusick # endif PC 3047953Speter inp = 0; 3053192Smckusick out = 0; 3063192Smckusick for (p = fp->chain; p != NIL; p = p->chain) { 3077953Speter if (strcmp(p->symbol, input->symbol) == 0) { 3083192Smckusick inp++; 3093192Smckusick continue; 3103192Smckusick } 3117953Speter if (strcmp(p->symbol, output->symbol) == 0) { 3123192Smckusick out++; 3133192Smckusick continue; 3143192Smckusick } 3153192Smckusick iop = lookup1(p->symbol); 3163192Smckusick if (iop == NIL || bn != cbn) { 3173192Smckusick error("File %s listed in program statement but not declared", p->symbol); 3183192Smckusick continue; 3193192Smckusick } 3203192Smckusick if (iop->class != VAR) { 3213192Smckusick error("File %s listed in program statement but declared as a %s", p->symbol, classes[iop->class]); 3223192Smckusick continue; 3233192Smckusick } 3243192Smckusick if (iop->type == NIL) 3253192Smckusick continue; 3263192Smckusick if (iop->type->class != FILET) { 3273192Smckusick error("File %s listed in program statement but defined as %s", 3283192Smckusick p->symbol, nameof(iop->type)); 3293192Smckusick continue; 3303192Smckusick } 3313192Smckusick # ifdef OBJ 3323192Smckusick put(2, O_CON24, text(iop->type) ? 0 : width(iop->type->type)); 3333192Smckusick i = lenstr(p->symbol,0); 3343192Smckusick put(2, O_CON24, i); 3353192Smckusick put(2, O_LVCON, i); 3363192Smckusick putstr(p->symbol, 0); 3373192Smckusick put(2, O_LV | bn<<8+INDX, (int)iop->value[NL_OFFS]); 3383192Smckusick put(1, O_DEFNAME); 3393192Smckusick # endif OBJ 3403192Smckusick # ifdef PC 3413192Smckusick putleaf( P2ICON , 0 , 0 3423192Smckusick , ADDTYPE( P2FTN | P2INT , P2PTR ) 3433192Smckusick , "_DEFNAME" ); 3443837Speter putLV( p -> symbol , bn , iop -> value[NL_OFFS] , 3453837Speter iop -> extra_flags , p2type( iop ) ); 3463192Smckusick putCONG( p -> symbol , strlen( p -> symbol ) 3473192Smckusick , LREQ ); 3483192Smckusick putop( P2LISTOP , P2INT ); 3493192Smckusick putleaf( P2ICON , strlen( p -> symbol ) 3503192Smckusick , 0 , P2INT , 0 ); 3513192Smckusick putop( P2LISTOP , P2INT ); 3523192Smckusick putleaf( P2ICON 3533192Smckusick , text(iop->type) ? 0 : width(iop->type->type) 3543192Smckusick , 0 , P2INT , 0 ); 3553192Smckusick putop( P2LISTOP , P2INT ); 3563192Smckusick putop( P2CALL , P2INT ); 3573192Smckusick putdot( filename , line ); 3583192Smckusick # endif PC 3593192Smckusick } 3603192Smckusick } 3613192Smckusick /* 3623192Smckusick * Process the prog/proc/func body 3633192Smckusick */ 3643192Smckusick noreach = 0; 3653192Smckusick line = bundle[1]; 3663192Smckusick statlist(blk); 3673192Smckusick # ifdef PTREE 3683192Smckusick { 3693192Smckusick pPointer Body = tCopy( blk ); 3703192Smckusick 3713192Smckusick pDEF( PorFHeader[ nesting -- ] ).PorFBody = Body; 3723192Smckusick } 3733192Smckusick # endif PTREE 3743192Smckusick # ifdef OBJ 3753192Smckusick if (cbn== 1 && monflg != 0) { 3763192Smckusick patchfil(cntpatch - 2, (long)cnts, 2); 3773192Smckusick patchfil(nfppatch - 2, (long)pfcnt, 2); 3783192Smckusick } 3793192Smckusick # endif OBJ 3803192Smckusick # ifdef PC 3813192Smckusick if ( fp -> class == PROG && monflg ) { 3823192Smckusick putleaf( P2ICON , 0 , 0 , ADDTYPE( P2FTN | P2INT , P2PTR ) 3833192Smckusick , "_PMFLUSH" ); 3843192Smckusick putleaf( P2ICON , cnts , 0 , P2INT , 0 ); 3853192Smckusick putleaf( P2ICON , pfcnt , 0 , P2INT , 0 ); 3863192Smckusick putop( P2LISTOP , P2INT ); 3873837Speter putLV( PCPCOUNT , 0 , 0 , NGLOBAL , P2INT ); 3883192Smckusick putop( P2LISTOP , P2INT ); 3893192Smckusick putop( P2CALL , P2INT ); 3903192Smckusick putdot( filename , line ); 3913192Smckusick } 3923192Smckusick # endif PC 3937953Speter /* 3947953Speter * Clean up the symbol table displays and check for unresolves 3957953Speter */ 3967953Speter line = endline; 3973192Smckusick if (fp->class == PROG && inp == 0 && (input->nl_flags & (NUSED|NMOD)) != 0) { 3983192Smckusick recovered(); 3993192Smckusick error("Input is used but not defined in the program statement"); 4003192Smckusick } 4017953Speter if (fp->class == PROG && out == 0 && (output->nl_flags & (NUSED|NMOD)) != 0) { 4027953Speter recovered(); 4037953Speter error("Output is used but not defined in the program statement"); 4047953Speter } 4053192Smckusick b = cbn; 4063192Smckusick Fp = fp; 4073192Smckusick chkref = syneflg == errcnt[cbn] && opt('w') == 0; 4083192Smckusick for (i = 0; i <= 077; i++) { 4093192Smckusick for (p = disptab[i]; p != NIL && (p->nl_block & 037) == b; p = p->nl_next) { 4103192Smckusick /* 4113192Smckusick * Check for variables defined 4123192Smckusick * but not referenced 4133192Smckusick */ 4143192Smckusick if (chkref && p->symbol != NIL) 4153192Smckusick switch (p->class) { 4163192Smckusick case FIELD: 4173192Smckusick /* 4183192Smckusick * If the corresponding record is 4193192Smckusick * unused, we shouldn't complain about 4203192Smckusick * the fields. 4213192Smckusick */ 4223192Smckusick default: 4233192Smckusick if ((p->nl_flags & (NUSED|NMOD)) == 0) { 4243192Smckusick warning(); 4253192Smckusick nerror("%s %s is neither used nor set", classes[p->class], p->symbol); 4263192Smckusick break; 4273192Smckusick } 4283192Smckusick /* 4293192Smckusick * If a var parameter is either 4303192Smckusick * modified or used that is enough. 4313192Smckusick */ 4323192Smckusick if (p->class == REF) 4333192Smckusick continue; 4343192Smckusick # ifdef OBJ 4353192Smckusick if ((p->nl_flags & NUSED) == 0) { 4363192Smckusick warning(); 4373192Smckusick nerror("%s %s is never used", classes[p->class], p->symbol); 4383192Smckusick break; 4393192Smckusick } 4403192Smckusick # endif OBJ 4413192Smckusick # ifdef PC 4423837Speter if (((p->nl_flags & NUSED) == 0) && ((p->extra_flags & NEXTERN) == 0)) { 4433192Smckusick warning(); 4443192Smckusick nerror("%s %s is never used", classes[p->class], p->symbol); 4453192Smckusick break; 4463192Smckusick } 4473192Smckusick # endif PC 4483192Smckusick if ((p->nl_flags & NMOD) == 0) { 4493192Smckusick warning(); 4503192Smckusick nerror("%s %s is used but never set", classes[p->class], p->symbol); 4513192Smckusick break; 4523192Smckusick } 4533192Smckusick case LABEL: 4543192Smckusick case FVAR: 4553192Smckusick case BADUSE: 4563192Smckusick break; 4573192Smckusick } 4583192Smckusick switch (p->class) { 4593192Smckusick case BADUSE: 4603192Smckusick cp = "s"; 4613192Smckusick if (p->chain->ud_next == NIL) 4623192Smckusick cp++; 4633192Smckusick eholdnl(); 4643192Smckusick if (p->value[NL_KINDS] & ISUNDEF) 4653192Smckusick nerror("%s undefined on line%s", p->symbol, cp); 4663192Smckusick else 4673192Smckusick nerror("%s improperly used on line%s", p->symbol, cp); 4683192Smckusick pnumcnt = 10; 4693192Smckusick pnums(p->chain); 4703192Smckusick pchr('\n'); 4713192Smckusick break; 4723192Smckusick 4733192Smckusick case FUNC: 4743192Smckusick case PROC: 4753192Smckusick # ifdef OBJ 4763192Smckusick if ((p->nl_flags & NFORWD)) 4773192Smckusick nerror("Unresolved forward declaration of %s %s", classes[p->class], p->symbol); 4783192Smckusick # endif OBJ 4793192Smckusick # ifdef PC 4803837Speter if ((p->nl_flags & NFORWD) && ((p->extra_flags & NEXTERN) == 0)) 4813192Smckusick nerror("Unresolved forward declaration of %s %s", classes[p->class], p->symbol); 4823192Smckusick # endif PC 4833192Smckusick break; 4843192Smckusick 4853192Smckusick case LABEL: 4863192Smckusick if (p->nl_flags & NFORWD) 4873192Smckusick nerror("label %s was declared but not defined", p->symbol); 4883192Smckusick break; 4893192Smckusick case FVAR: 4903192Smckusick if ((p->nl_flags & NMOD) == 0) 4913192Smckusick nerror("No assignment to the function variable"); 4923192Smckusick break; 4933192Smckusick } 4943192Smckusick } 4953192Smckusick /* 4963192Smckusick * Pop this symbol 4973192Smckusick * table slot 4983192Smckusick */ 4993192Smckusick disptab[i] = p; 5003192Smckusick } 5013192Smckusick 5023192Smckusick # ifdef OBJ 5033192Smckusick put(1, O_END); 5043192Smckusick # endif OBJ 5053192Smckusick # ifdef PC 5063192Smckusick /* 5073192Smckusick * if there were file variables declared at this level 5089127Smckusick * call PCLOSE( ap ) to clean them up. 5093192Smckusick */ 5103192Smckusick if ( dfiles[ cbn ] ) { 5113192Smckusick putleaf( P2ICON , 0 , 0 , ADDTYPE( P2FTN | P2INT , P2PTR ) 5123192Smckusick , "_PCLOSE" ); 5139127Smckusick putleaf( P2REG , 0 , P2AP , ADDTYPE( P2CHAR , P2PTR ) , 0 ); 5143192Smckusick putop( P2CALL , P2INT ); 5153192Smckusick putdot( filename , line ); 5163192Smckusick } 5173192Smckusick /* 5183192Smckusick * if this is a function, 5193192Smckusick * the function variable is the return value. 5203192Smckusick * if it's a scalar valued function, return scalar, 5213192Smckusick * else, return a pointer to the structure value. 5223192Smckusick */ 5233192Smckusick if ( fp -> class == FUNC ) { 5243192Smckusick struct nl *fvar = fp -> ptr[ NL_FVAR ]; 5253192Smckusick long fvartype = p2type( fvar -> type ); 5263192Smckusick long label; 5273192Smckusick char labelname[ BUFSIZ ]; 5283192Smckusick 5293192Smckusick switch ( classify( fvar -> type ) ) { 5303192Smckusick case TBOOL: 5313192Smckusick case TCHAR: 5323192Smckusick case TINT: 5333192Smckusick case TSCAL: 5343192Smckusick case TDOUBLE: 5353192Smckusick case TPTR: 5363837Speter putRV( fvar -> symbol , ( fvar -> nl_block ) & 037 , 5373837Speter fvar -> value[ NL_OFFS ] , 5383837Speter fvar -> extra_flags , 5393837Speter fvartype ); 5403192Smckusick break; 5413192Smckusick default: 5423192Smckusick label = getlab(); 5433192Smckusick sprintf( labelname , PREFIXFORMAT , 5443192Smckusick LABELPREFIX , label ); 5453192Smckusick putprintf( " .data" , 0 ); 5463192Smckusick putprintf( " .lcomm %s,%d" , 0 , 5473192Smckusick labelname , lwidth( fvar -> type ) ); 5483192Smckusick putprintf( " .text" , 0 ); 5493192Smckusick putleaf( P2NAME , 0 , 0 , fvartype , labelname ); 5503837Speter putLV( fvar -> symbol , ( fvar -> nl_block ) & 037 , 5513837Speter fvar -> value[ NL_OFFS ] , 5523837Speter fvar -> extra_flags , 5533837Speter fvartype ); 5543192Smckusick putstrop( P2STASG , fvartype , lwidth( fvar -> type ) , 5553192Smckusick align( fvar -> type ) ); 5563192Smckusick putdot( filename , line ); 5573192Smckusick putleaf( P2ICON , 0 , 0 , fvartype , labelname ); 5583192Smckusick break; 5593192Smckusick } 5603192Smckusick putop( P2FORCE , fvartype ); 5613192Smckusick putdot( filename , line ); 5623192Smckusick } 5633192Smckusick /* 5649127Smckusick * if there are nested procedures we must save the display. 5653192Smckusick */ 5669127Smckusick if ( parts[ cbn ] & NONLOCALVAR ) { 5679127Smckusick /* 5689127Smckusick * restore old display entry from save area 5699127Smckusick */ 5709127Smckusick putprintf( " movq %d(%s),%s+%d" , 0 5719127Smckusick , DSAVEOFFSET , P2FPNAME 5729127Smckusick , DISPLAYNAME , cbn * sizeof(struct dispsave) ); 5739127Smckusick } 5743192Smckusick stabrbrac( cbn ); 5753192Smckusick putprintf( " ret" , 0 ); 5763192Smckusick /* 5773192Smckusick * let the second pass allocate locals 5783279Smckusic * and registers 5793192Smckusick */ 5803279Smckusic putprintf( " .set " , 1 ); 5813279Smckusic putprintf( PREFIXFORMAT , 1 , LABELPREFIX , savlabel ); 5823279Smckusic putprintf( ", 0x%x" , 0 , savmask() ); 5833192Smckusick putrbracket( ftnno ); 5843192Smckusick /* 5853428Speter * put down the entry point for formal calls 5863428Speter * the arguments for FCALL have been passed to us 5873428Speter * as hidden parameters after the regular arguments. 5883428Speter */ 5893428Speter if ( fp -> class != PROG ) { 5903428Speter putprintf( "%s%s:" , 0 , FORMALPREFIX , extname ); 5913428Speter putprintf( " .word " , 1 ); 5923428Speter putprintf( PREFIXFORMAT , 0 , LABELPREFIX , savlabel ); 5933428Speter putleaf( P2ICON , 0 , 0 , ADDTYPE( P2FTN | P2INT , P2PTR ) , 5943428Speter "_FCALL" ); 5953428Speter putRV( 0 , cbn , 5963428Speter fp -> value[ NL_OFFS ] + sizeof( struct formalrtn * ) , 5973837Speter NPARAM , 5983428Speter P2PTR | P2STRTY ); 5993837Speter putRV( 0 , cbn , fp -> value[ NL_OFFS ] , 6003837Speter NPARAM , P2PTR|P2STRTY ); 6013428Speter putop( P2LISTOP , P2INT ); 6023428Speter putop( P2CALL , P2INT ); 6033428Speter putdot( filename , line ); 6049127Smckusick putjbr( toplabel ); 6053428Speter } 6063428Speter /* 6073192Smckusick * declare pcp counters, if any 6083192Smckusick */ 6093192Smckusick if ( monflg && fp -> class == PROG ) { 6103192Smckusick putprintf( " .data" , 0 ); 6113192Smckusick putprintf( " .comm " , 1 ); 6123192Smckusick putprintf( PCPCOUNT , 1 ); 6133192Smckusick putprintf( ",%d" , 0 , ( cnts + 1 ) * sizeof (long) ); 6143192Smckusick putprintf( " .text" , 0 ); 6153192Smckusick } 6163192Smckusick # endif PC 6173192Smckusick #ifdef DEBUG 6183192Smckusick dumpnl(fp->ptr[2], fp->symbol); 6193192Smckusick #endif 6205654Slinton 6215654Slinton #ifdef OBJ 6223192Smckusick /* 6235654Slinton * save the namelist for the debugger pdx 6245654Slinton */ 6255654Slinton 6265654Slinton savenl(fp->ptr[2], fp->symbol); 6275654Slinton #endif 6285654Slinton 6295654Slinton /* 6303192Smckusick * Restore the 6313192Smckusick * (virtual) name list 6323192Smckusick * position 6333192Smckusick */ 6343192Smckusick nlfree(fp->ptr[2]); 6353192Smckusick /* 6363192Smckusick * Proc/func has been 6373192Smckusick * resolved 6383192Smckusick */ 6393192Smckusick fp->nl_flags &= ~NFORWD; 6403192Smckusick /* 6413192Smckusick * Patch the beg 6423192Smckusick * of the proc/func to 6433192Smckusick * the proper variable size 6443192Smckusick */ 6453192Smckusick if (Fp == NIL) 6463192Smckusick elineon(); 6473192Smckusick # ifdef OBJ 6483192Smckusick patchfil(var, (long)(-sizes[cbn].om_max), 2); 6493192Smckusick # endif OBJ 6503192Smckusick cbn--; 6513192Smckusick if (inpflist(fp->symbol)) { 6523192Smckusick opop('l'); 6533192Smckusick } 6543192Smckusick } 6553363Speter 6563363Speter #ifdef PC 6573363Speter /* 6583363Speter * construct the long name of a function based on it's static nesting. 6593363Speter * into a caller-supplied buffer (that should be about BUFSIZ big). 6603363Speter */ 6613363Speter sextname( buffer , name , level ) 6623363Speter char buffer[]; 6633363Speter char *name; 6643363Speter int level; 6653363Speter { 6663363Speter char *starthere; 6673363Speter int i; 6683363Speter 6693363Speter starthere = &buffer[0]; 6703363Speter for ( i = 1 ; i < level ; i++ ) { 6713363Speter sprintf( starthere , EXTFORMAT , enclosing[ i ] ); 6723363Speter starthere += strlen( enclosing[ i ] ) + 1; 6733363Speter } 6743367Speter sprintf( starthere , EXTFORMAT , name ); 6753367Speter starthere += strlen( name ) + 1; 6763363Speter if ( starthere >= &buffer[ BUFSIZ ] ) { 6773363Speter panic( "sextname" ); 6783363Speter } 6793363Speter } 6803363Speter #endif PC 681