13192Smckusick /* Copyright (c) 1979 Regents of the University of California */ 23192Smckusick 3*10671Speter static char sccsid[] = "@(#)fend.c 1.18 02/01/83"; 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 55*10671Speter struct entry_exit_cookie eecookie; 563192Smckusick # endif PC 573192Smckusick 583192Smckusick cntstat = 0; 593192Smckusick /* 603192Smckusick * yyoutline(); 613192Smckusick */ 623192Smckusick if (program != NIL) 633192Smckusick line = program->value[3]; 643192Smckusick blk = bundle[2]; 653192Smckusick if (fp == NIL) { 663192Smckusick cbn--; 673192Smckusick # ifdef PTREE 683192Smckusick nesting--; 693192Smckusick # endif PTREE 703192Smckusick return; 713192Smckusick } 723192Smckusick #ifdef OBJ 733192Smckusick /* 743192Smckusick * Patch the branch to the 753192Smckusick * entry point of the function 763192Smckusick */ 777917Smckusick patch4(fp->value[NL_ENTLOC]); 783192Smckusick /* 793192Smckusick * Put out the block entrance code and the block name. 803192Smckusick * HDRSZE is the number of bytes of info in the static 813192Smckusick * BEG data area exclusive of the proc name. It is 823192Smckusick * currently defined as: 833192Smckusick /* struct hdr { 843192Smckusick /* long framesze; /* number of bytes of local vars */ 853192Smckusick /* long nargs; /* number of bytes of arguments */ 863192Smckusick /* bool tests; /* TRUE => perform runtime tests */ 873192Smckusick /* short offset; /* offset of procedure in source file */ 883192Smckusick /* char name[1]; /* name of active procedure */ 893192Smckusick /* }; 903192Smckusick */ 913192Smckusick # define HDRSZE (2 * sizeof(long) + sizeof(short) + sizeof(bool)) 923192Smckusick var = put(2, ((lenstr(fp->symbol,0) + HDRSZE) << 8) 933192Smckusick | (cbn == 1 && opt('p') == 0 ? O_NODUMP: O_BEG), (long)0); 943192Smckusick /* 953192Smckusick * output the number of bytes of arguments 963192Smckusick * this is only checked on formal calls. 973192Smckusick */ 983192Smckusick put(2, O_CASE4, cbn == 1 ? (long)0 : (long)(fp->value[NL_OFFS]-DPOFF2)); 993192Smckusick /* 1003192Smckusick * Output the runtime test mode for the routine 1013192Smckusick */ 1023192Smckusick put(2, sizeof(bool) == 2 ? O_CASE2 : O_CASE4, opt('t') ? TRUE : FALSE); 1033192Smckusick /* 1043192Smckusick * Output line number and routine name 1053192Smckusick */ 1063192Smckusick put(2, O_CASE2, bundle[1]); 1073192Smckusick putstr(fp->symbol, 0); 1083192Smckusick #endif OBJ 1093192Smckusick #ifdef PC 1103192Smckusick /* 1113192Smckusick * put out the procedure entry code 1123192Smckusick */ 113*10671Speter eecookie.nlp = fp; 1143192Smckusick if ( fp -> class == PROG ) { 1159129Smckusick /* 1169129Smckusick * If there is a label declaration in the main routine 1179129Smckusick * then there may be a non-local goto to it that does 1189129Smckusick * not appear in this module. We have to assume that 1199129Smckusick * such a reference may occur and generate code to 1209129Smckusick * prepare for it. 1219129Smckusick */ 1229129Smckusick if ( parts[ cbn ] & LPRT ) { 1239129Smckusick parts[ cbn ] |= ( NONLOCALVAR | NONLOCALGOTO ); 1249129Smckusick } 125*10671Speter codeformain(); 1267917Smckusick ftnno = fp -> value[NL_ENTLOC]; 127*10671Speter prog_prologue(&eecookie); 1283192Smckusick stabfunc( "program" , fp -> class , bundle[1] , 0 ); 1293192Smckusick } else { 1307917Smckusick ftnno = fp -> value[NL_ENTLOC]; 131*10671Speter fp_prologue(&eecookie); 1323192Smckusick stabfunc( fp -> symbol , fp -> class , bundle[1] , cbn - 1 ); 1333192Smckusick for ( p = fp -> chain ; p != NIL ; p = p -> chain ) { 1343192Smckusick stabparam( p -> symbol , p2type( p -> type ) 1353192Smckusick , p -> value[ NL_OFFS ] , lwidth( p -> type ) ); 1363192Smckusick } 1373192Smckusick if ( fp -> class == FUNC ) { 1383192Smckusick /* 1393192Smckusick * stab the function variable 1403192Smckusick */ 1413192Smckusick p = fp -> ptr[ NL_FVAR ]; 1423192Smckusick stablvar( p -> symbol , p2type( p -> type ) , cbn 1433192Smckusick , p -> value[ NL_OFFS ] , lwidth( p -> type ) ); 1443192Smckusick } 1453192Smckusick /* 1463192Smckusick * stab local variables 1473192Smckusick * rummage down hash chain links. 1483192Smckusick */ 1493192Smckusick for ( i = 0 ; i <= 077 ; i++ ) { 1503192Smckusick for ( p = disptab[ i ] ; p != NIL ; p = p->nl_next) { 1513192Smckusick if ( ( p -> nl_block & 037 ) != cbn ) { 1523192Smckusick break; 1533192Smckusick } 1543192Smckusick /* 1553192Smckusick * stab local variables 1563192Smckusick * that's named variables, but not params 1573192Smckusick */ 1583192Smckusick if ( ( p -> symbol != NIL ) 1593192Smckusick && ( p -> class == VAR ) 1603192Smckusick && ( p -> value[ NL_OFFS ] < 0 ) ) { 1613192Smckusick stablvar( p -> symbol , p2type( p -> type ) , cbn 1623192Smckusick , p -> value[ NL_OFFS ] , lwidth( p -> type ) ); 1633192Smckusick } 1643192Smckusick } 1653192Smckusick } 1663192Smckusick } 1673192Smckusick stablbrac( cbn ); 1683192Smckusick /* 1693192Smckusick * ask second pass to allocate known locals 1703192Smckusick */ 1713192Smckusick putlbracket( ftnno , -sizes[ cbn ].om_max ); 172*10671Speter fp_entrycode(&eecookie); 1733192Smckusick #endif PC 1743192Smckusick if ( monflg ) { 1753192Smckusick if ( fp -> value[ NL_CNTR ] != 0 ) { 1763192Smckusick inccnt( fp -> value [ NL_CNTR ] ); 1773192Smckusick } 1783192Smckusick inccnt( bodycnts[ fp -> nl_block & 037 ] ); 1793192Smckusick } 1803192Smckusick if (fp->class == PROG) { 1813192Smckusick /* 1823192Smckusick * The glorious buffers option. 1833192Smckusick * 0 = don't buffer output 1843192Smckusick * 1 = line buffer output 1853192Smckusick * 2 = 512 byte buffer output 1863192Smckusick */ 1873192Smckusick # ifdef OBJ 1883192Smckusick if (opt('b') != 1) 1893192Smckusick put(1, O_BUFF | opt('b') << 8); 1903192Smckusick # endif OBJ 1913192Smckusick # ifdef PC 1923192Smckusick if ( opt( 'b' ) != 1 ) { 1933192Smckusick putleaf( P2ICON , 0 , 0 1943192Smckusick , ADDTYPE( P2FTN | P2INT , P2PTR ) , "_BUFF" ); 1953192Smckusick putleaf( P2ICON , opt( 'b' ) , 0 , P2INT , 0 ); 1963192Smckusick putop( P2CALL , P2INT ); 1973192Smckusick putdot( filename , line ); 1983192Smckusick } 1993192Smckusick # endif PC 2007953Speter inp = 0; 2013192Smckusick out = 0; 2023192Smckusick for (p = fp->chain; p != NIL; p = p->chain) { 2037953Speter if (strcmp(p->symbol, input->symbol) == 0) { 2043192Smckusick inp++; 2053192Smckusick continue; 2063192Smckusick } 2077953Speter if (strcmp(p->symbol, output->symbol) == 0) { 2083192Smckusick out++; 2093192Smckusick continue; 2103192Smckusick } 2113192Smckusick iop = lookup1(p->symbol); 2123192Smckusick if (iop == NIL || bn != cbn) { 2133192Smckusick error("File %s listed in program statement but not declared", p->symbol); 2143192Smckusick continue; 2153192Smckusick } 2163192Smckusick if (iop->class != VAR) { 2173192Smckusick error("File %s listed in program statement but declared as a %s", p->symbol, classes[iop->class]); 2183192Smckusick continue; 2193192Smckusick } 2203192Smckusick if (iop->type == NIL) 2213192Smckusick continue; 2223192Smckusick if (iop->type->class != FILET) { 2233192Smckusick error("File %s listed in program statement but defined as %s", 2243192Smckusick p->symbol, nameof(iop->type)); 2253192Smckusick continue; 2263192Smckusick } 2273192Smckusick # ifdef OBJ 2283192Smckusick put(2, O_CON24, text(iop->type) ? 0 : width(iop->type->type)); 2293192Smckusick i = lenstr(p->symbol,0); 2303192Smckusick put(2, O_CON24, i); 2313192Smckusick put(2, O_LVCON, i); 2323192Smckusick putstr(p->symbol, 0); 2333192Smckusick put(2, O_LV | bn<<8+INDX, (int)iop->value[NL_OFFS]); 2343192Smckusick put(1, O_DEFNAME); 2353192Smckusick # endif OBJ 2363192Smckusick # ifdef PC 2373192Smckusick putleaf( P2ICON , 0 , 0 2383192Smckusick , ADDTYPE( P2FTN | P2INT , P2PTR ) 2393192Smckusick , "_DEFNAME" ); 2403837Speter putLV( p -> symbol , bn , iop -> value[NL_OFFS] , 2413837Speter iop -> extra_flags , p2type( iop ) ); 2423192Smckusick putCONG( p -> symbol , strlen( p -> symbol ) 2433192Smckusick , LREQ ); 2443192Smckusick putop( P2LISTOP , P2INT ); 2453192Smckusick putleaf( P2ICON , strlen( p -> symbol ) 2463192Smckusick , 0 , P2INT , 0 ); 2473192Smckusick putop( P2LISTOP , P2INT ); 2483192Smckusick putleaf( P2ICON 2493192Smckusick , text(iop->type) ? 0 : width(iop->type->type) 2503192Smckusick , 0 , P2INT , 0 ); 2513192Smckusick putop( P2LISTOP , P2INT ); 2523192Smckusick putop( P2CALL , P2INT ); 2533192Smckusick putdot( filename , line ); 2543192Smckusick # endif PC 2553192Smckusick } 2563192Smckusick } 2573192Smckusick /* 2583192Smckusick * Process the prog/proc/func body 2593192Smckusick */ 2603192Smckusick noreach = 0; 2613192Smckusick line = bundle[1]; 2623192Smckusick statlist(blk); 2633192Smckusick # ifdef PTREE 2643192Smckusick { 2653192Smckusick pPointer Body = tCopy( blk ); 2663192Smckusick 2673192Smckusick pDEF( PorFHeader[ nesting -- ] ).PorFBody = Body; 2683192Smckusick } 2693192Smckusick # endif PTREE 2703192Smckusick # ifdef OBJ 2713192Smckusick if (cbn== 1 && monflg != 0) { 2723192Smckusick patchfil(cntpatch - 2, (long)cnts, 2); 2733192Smckusick patchfil(nfppatch - 2, (long)pfcnt, 2); 2743192Smckusick } 2753192Smckusick # endif OBJ 2763192Smckusick # ifdef PC 2773192Smckusick if ( fp -> class == PROG && monflg ) { 2783192Smckusick putleaf( P2ICON , 0 , 0 , ADDTYPE( P2FTN | P2INT , P2PTR ) 2793192Smckusick , "_PMFLUSH" ); 2803192Smckusick putleaf( P2ICON , cnts , 0 , P2INT , 0 ); 2813192Smckusick putleaf( P2ICON , pfcnt , 0 , P2INT , 0 ); 2823192Smckusick putop( P2LISTOP , P2INT ); 2833837Speter putLV( PCPCOUNT , 0 , 0 , NGLOBAL , P2INT ); 2843192Smckusick putop( P2LISTOP , P2INT ); 2853192Smckusick putop( P2CALL , P2INT ); 2863192Smckusick putdot( filename , line ); 2873192Smckusick } 2883192Smckusick # endif PC 2897953Speter /* 2907953Speter * Clean up the symbol table displays and check for unresolves 2917953Speter */ 2927953Speter line = endline; 2933192Smckusick if (fp->class == PROG && inp == 0 && (input->nl_flags & (NUSED|NMOD)) != 0) { 2943192Smckusick recovered(); 2953192Smckusick error("Input is used but not defined in the program statement"); 2963192Smckusick } 2977953Speter if (fp->class == PROG && out == 0 && (output->nl_flags & (NUSED|NMOD)) != 0) { 2987953Speter recovered(); 2997953Speter error("Output is used but not defined in the program statement"); 3007953Speter } 3013192Smckusick b = cbn; 3023192Smckusick Fp = fp; 3033192Smckusick chkref = syneflg == errcnt[cbn] && opt('w') == 0; 3043192Smckusick for (i = 0; i <= 077; i++) { 3053192Smckusick for (p = disptab[i]; p != NIL && (p->nl_block & 037) == b; p = p->nl_next) { 3063192Smckusick /* 3073192Smckusick * Check for variables defined 3083192Smckusick * but not referenced 3093192Smckusick */ 3103192Smckusick if (chkref && p->symbol != NIL) 3113192Smckusick switch (p->class) { 3123192Smckusick case FIELD: 3133192Smckusick /* 3143192Smckusick * If the corresponding record is 3153192Smckusick * unused, we shouldn't complain about 3163192Smckusick * the fields. 3173192Smckusick */ 3183192Smckusick default: 3193192Smckusick if ((p->nl_flags & (NUSED|NMOD)) == 0) { 3203192Smckusick warning(); 3213192Smckusick nerror("%s %s is neither used nor set", classes[p->class], p->symbol); 3223192Smckusick break; 3233192Smckusick } 3243192Smckusick /* 3253192Smckusick * If a var parameter is either 3263192Smckusick * modified or used that is enough. 3273192Smckusick */ 3283192Smckusick if (p->class == REF) 3293192Smckusick continue; 3303192Smckusick # ifdef OBJ 3313192Smckusick if ((p->nl_flags & NUSED) == 0) { 3323192Smckusick warning(); 3333192Smckusick nerror("%s %s is never used", classes[p->class], p->symbol); 3343192Smckusick break; 3353192Smckusick } 3363192Smckusick # endif OBJ 3373192Smckusick # ifdef PC 3383837Speter if (((p->nl_flags & NUSED) == 0) && ((p->extra_flags & NEXTERN) == 0)) { 3393192Smckusick warning(); 3403192Smckusick nerror("%s %s is never used", classes[p->class], p->symbol); 3413192Smckusick break; 3423192Smckusick } 3433192Smckusick # endif PC 3443192Smckusick if ((p->nl_flags & NMOD) == 0) { 3453192Smckusick warning(); 3463192Smckusick nerror("%s %s is used but never set", classes[p->class], p->symbol); 3473192Smckusick break; 3483192Smckusick } 3493192Smckusick case LABEL: 3503192Smckusick case FVAR: 3513192Smckusick case BADUSE: 3523192Smckusick break; 3533192Smckusick } 3543192Smckusick switch (p->class) { 3553192Smckusick case BADUSE: 3563192Smckusick cp = "s"; 3573192Smckusick if (p->chain->ud_next == NIL) 3583192Smckusick cp++; 3593192Smckusick eholdnl(); 3603192Smckusick if (p->value[NL_KINDS] & ISUNDEF) 3613192Smckusick nerror("%s undefined on line%s", p->symbol, cp); 3623192Smckusick else 3633192Smckusick nerror("%s improperly used on line%s", p->symbol, cp); 3643192Smckusick pnumcnt = 10; 3653192Smckusick pnums(p->chain); 3663192Smckusick pchr('\n'); 3673192Smckusick break; 3683192Smckusick 3693192Smckusick case FUNC: 3703192Smckusick case PROC: 3713192Smckusick # ifdef OBJ 3723192Smckusick if ((p->nl_flags & NFORWD)) 3733192Smckusick nerror("Unresolved forward declaration of %s %s", classes[p->class], p->symbol); 3743192Smckusick # endif OBJ 3753192Smckusick # ifdef PC 3763837Speter if ((p->nl_flags & NFORWD) && ((p->extra_flags & NEXTERN) == 0)) 3773192Smckusick nerror("Unresolved forward declaration of %s %s", classes[p->class], p->symbol); 3783192Smckusick # endif PC 3793192Smckusick break; 3803192Smckusick 3813192Smckusick case LABEL: 3823192Smckusick if (p->nl_flags & NFORWD) 3833192Smckusick nerror("label %s was declared but not defined", p->symbol); 3843192Smckusick break; 3853192Smckusick case FVAR: 3863192Smckusick if ((p->nl_flags & NMOD) == 0) 3873192Smckusick nerror("No assignment to the function variable"); 3883192Smckusick break; 3893192Smckusick } 3903192Smckusick } 3913192Smckusick /* 3923192Smckusick * Pop this symbol 3933192Smckusick * table slot 3943192Smckusick */ 3953192Smckusick disptab[i] = p; 3963192Smckusick } 3973192Smckusick 3983192Smckusick # ifdef OBJ 3993192Smckusick put(1, O_END); 4003192Smckusick # endif OBJ 4013192Smckusick # ifdef PC 402*10671Speter fp_exitcode(&eecookie); 403*10671Speter stabrbrac(cbn); 404*10671Speter putrbracket(ftnno); 405*10671Speter fp_epilogue(&eecookie); 406*10671Speter if (fp -> class != PROG) { 407*10671Speter fp_formalentry(&eecookie); 4083192Smckusick } 4093192Smckusick /* 4103192Smckusick * declare pcp counters, if any 4113192Smckusick */ 4123192Smckusick if ( monflg && fp -> class == PROG ) { 4133192Smckusick putprintf( " .data" , 0 ); 414*10671Speter aligndot(P2INT); 4153192Smckusick putprintf( " .comm " , 1 ); 4163192Smckusick putprintf( PCPCOUNT , 1 ); 4173192Smckusick putprintf( ",%d" , 0 , ( cnts + 1 ) * sizeof (long) ); 4183192Smckusick putprintf( " .text" , 0 ); 4193192Smckusick } 4203192Smckusick # endif PC 4213192Smckusick #ifdef DEBUG 4223192Smckusick dumpnl(fp->ptr[2], fp->symbol); 4233192Smckusick #endif 4245654Slinton 4255654Slinton #ifdef OBJ 4263192Smckusick /* 4275654Slinton * save the namelist for the debugger pdx 4285654Slinton */ 4295654Slinton 4305654Slinton savenl(fp->ptr[2], fp->symbol); 4315654Slinton #endif 4325654Slinton 4335654Slinton /* 4343192Smckusick * Restore the 4353192Smckusick * (virtual) name list 4363192Smckusick * position 4373192Smckusick */ 4383192Smckusick nlfree(fp->ptr[2]); 4393192Smckusick /* 4403192Smckusick * Proc/func has been 4413192Smckusick * resolved 4423192Smckusick */ 4433192Smckusick fp->nl_flags &= ~NFORWD; 4443192Smckusick /* 4453192Smckusick * Patch the beg 4463192Smckusick * of the proc/func to 4473192Smckusick * the proper variable size 4483192Smckusick */ 4493192Smckusick if (Fp == NIL) 4503192Smckusick elineon(); 4513192Smckusick # ifdef OBJ 452*10671Speter patchfil(var, leven(-sizes[cbn].om_max), 2); 4533192Smckusick # endif OBJ 4543192Smckusick cbn--; 4553192Smckusick if (inpflist(fp->symbol)) { 4563192Smckusick opop('l'); 4573192Smckusick } 4583192Smckusick } 4593363Speter 4603363Speter #ifdef PC 4613363Speter /* 4623363Speter * construct the long name of a function based on it's static nesting. 4633363Speter * into a caller-supplied buffer (that should be about BUFSIZ big). 4643363Speter */ 4653363Speter sextname( buffer , name , level ) 4663363Speter char buffer[]; 4673363Speter char *name; 4683363Speter int level; 4693363Speter { 4703363Speter char *starthere; 4713363Speter int i; 4723363Speter 4733363Speter starthere = &buffer[0]; 4743363Speter for ( i = 1 ; i < level ; i++ ) { 4753363Speter sprintf( starthere , EXTFORMAT , enclosing[ i ] ); 4763363Speter starthere += strlen( enclosing[ i ] ) + 1; 4773363Speter } 4783367Speter sprintf( starthere , EXTFORMAT , name ); 4793367Speter starthere += strlen( name ) + 1; 4803363Speter if ( starthere >= &buffer[ BUFSIZ ] ) { 4813363Speter panic( "sextname" ); 4823363Speter } 4833363Speter } 484*10671Speter 485*10671Speter /* 486*10671Speter * code for main() 487*10671Speter */ 488*10671Speter #ifdef vax 489*10671Speter 490*10671Speter codeformain() 491*10671Speter { 492*10671Speter putprintf(" .text" , 0 ); 493*10671Speter putprintf(" .align 1" , 0 ); 494*10671Speter putprintf(" .globl _main" , 0 ); 495*10671Speter putprintf("_main:" , 0 ); 496*10671Speter putprintf(" .word 0" , 0 ); 497*10671Speter if ( opt ( 't' ) ) { 498*10671Speter putprintf(" pushl $1" , 0 ); 499*10671Speter } else { 500*10671Speter putprintf(" pushl $0" , 0 ); 501*10671Speter } 502*10671Speter putprintf(" calls $1,_PCSTART" , 0 ); 503*10671Speter putprintf(" movl 4(ap),__argc" , 0 ); 504*10671Speter putprintf(" movl 8(ap),__argv" , 0 ); 505*10671Speter putprintf(" calls $0,_program" , 0 ); 506*10671Speter putprintf(" pushl $0" , 0 ); 507*10671Speter putprintf(" calls $1,_PCEXIT" , 0 ); 508*10671Speter } 509*10671Speter 510*10671Speter /* 511*10671Speter * prologue for the program. 512*10671Speter * different because it 513*10671Speter * doesn't have formal entry point 514*10671Speter */ 515*10671Speter prog_prologue(eecookiep) 516*10671Speter struct entry_exit_cookie *eecookiep; 517*10671Speter { 518*10671Speter putprintf(" .text" , 0 ); 519*10671Speter putprintf(" .align 1" , 0 ); 520*10671Speter putprintf(" .globl _program" , 0 ); 521*10671Speter putprintf("_program:" , 0 ); 522*10671Speter } 523*10671Speter 524*10671Speter fp_prologue(eecookiep) 525*10671Speter struct entry_exit_cookie *eecookiep; 526*10671Speter { 527*10671Speter int ftnno = eecookiep -> nlp -> value[NL_ENTLOC]; 528*10671Speter 529*10671Speter sextname( eecookiep -> extname, eecookiep -> nlp -> symbol , cbn - 1 ); 530*10671Speter putprintf( " .text" , 0 ); 531*10671Speter putprintf( " .align 1" , 0 ); 532*10671Speter putprintf( " .globl %s%s", 0, FORMALPREFIX, eecookiep -> extname ); 533*10671Speter putprintf( " .globl %s" , 0 , eecookiep -> extname ); 534*10671Speter putprintf( "%s:" , 0 , eecookiep -> extname ); 535*10671Speter /* 536*10671Speter * register save mask 537*10671Speter */ 538*10671Speter eecookiep -> savlabel = getlab(); 539*10671Speter putprintf(" .word %s%d", 0, SAVE_MASK_LABEL , eecookiep -> savlabel ); 540*10671Speter } 541*10671Speter 542*10671Speter /* 543*10671Speter * code before any user code. 544*10671Speter * or code that is machine dependent. 545*10671Speter */ 546*10671Speter fp_entrycode(eecookiep) 547*10671Speter struct entry_exit_cookie *eecookiep; 548*10671Speter { 549*10671Speter int ftnno = eecookiep -> nlp -> nl_value[ENTLOC]; 550*10671Speter int proflabel = getlab(); 551*10671Speter int setjmp0 = getlab(); 552*10671Speter 553*10671Speter /* 554*10671Speter * top of code; destination of jump from formal entry code. 555*10671Speter */ 556*10671Speter eecookiep -> toplabel = getlab(); 557*10671Speter putlab( eecookiep -> toplabel ); 558*10671Speter putprintf(" subl2 $%s%d,sp" , 0 , FRAME_SIZE_LABEL, ftnno ); 559*10671Speter if ( profflag ) { 560*10671Speter /* 561*10671Speter * call mcount for profiling 562*10671Speter */ 563*10671Speter putprintf( " moval " , 1 ); 564*10671Speter putprintf( PREFIXFORMAT , 1 , LABELPREFIX , proflabel ); 565*10671Speter putprintf( ",r0" , 0 ); 566*10671Speter putprintf( " jsb mcount" , 0 ); 567*10671Speter putprintf( " .data" , 0 ); 568*10671Speter putprintf( " .align 2" , 0 ); 569*10671Speter putlab( proflabel ); 570*10671Speter putprintf( " .long 0" , 0 ); 571*10671Speter putprintf( " .text" , 0 ); 572*10671Speter } 573*10671Speter /* 574*10671Speter * if there are nested procedures that access our variables 575*10671Speter * we must save the display. 576*10671Speter */ 577*10671Speter if ( parts[ cbn ] & NONLOCALVAR ) { 578*10671Speter /* 579*10671Speter * save old display 580*10671Speter */ 581*10671Speter putprintf( " movq %s+%d,%d(%s)" , 0 582*10671Speter , DISPLAYNAME , cbn * sizeof(struct dispsave) 583*10671Speter , DSAVEOFFSET , P2FPNAME ); 584*10671Speter /* 585*10671Speter * set up new display by saving AP and FP in appropriate 586*10671Speter * slot in display structure. 587*10671Speter */ 588*10671Speter putprintf( " movq %s,%s+%d" , 0 589*10671Speter , P2APNAME , DISPLAYNAME , cbn * sizeof(struct dispsave) ); 590*10671Speter } 591*10671Speter /* 592*10671Speter * set underflow checking if runtime tests 593*10671Speter */ 594*10671Speter if ( opt( 't' ) ) { 595*10671Speter putprintf( " bispsw $0xe0" , 0 ); 596*10671Speter } 597*10671Speter /* 598*10671Speter * zero local variables if checking is on 599*10671Speter * by calling blkclr( bytes of locals , starting local address ); 600*10671Speter */ 601*10671Speter if ( opt( 't' ) && ( -sizes[ cbn ].om_max ) > DPOFF1 ) { 602*10671Speter putleaf( P2ICON , 0 , 0 , ADDTYPE( P2FTN | P2INT , P2PTR ) 603*10671Speter , "_blkclr" ); 604*10671Speter putLV( 0 , cbn , sizes[ cbn ].om_max , NLOCAL , P2CHAR ); 605*10671Speter putleaf( P2ICON , ( -sizes[ cbn ].om_max ) - DPOFF1 606*10671Speter , 0 , P2INT , 0 ); 607*10671Speter putop( P2LISTOP , P2INT ); 608*10671Speter putop( P2CALL , P2INT ); 609*10671Speter putdot( filename , line ); 610*10671Speter } 611*10671Speter /* 612*10671Speter * set up goto vector if non-local goto to this frame 613*10671Speter */ 614*10671Speter if ( parts[ cbn ] & NONLOCALGOTO ) { 615*10671Speter putleaf( P2ICON , 0 , 0 , ADDTYPE( P2FTN | P2INT , P2PTR ) 616*10671Speter , "_setjmp" ); 617*10671Speter putLV( 0 , cbn , GOTOENVOFFSET , NLOCAL , P2PTR|P2STRTY ); 618*10671Speter putop( P2CALL , P2INT ); 619*10671Speter putleaf( P2ICON , 0 , 0 , P2INT , 0 ); 620*10671Speter putop( P2NE , P2INT ); 621*10671Speter putleaf( P2ICON , setjmp0 , 0 , P2INT , 0 ); 622*10671Speter putop( P2CBRANCH , P2INT ); 623*10671Speter putdot( filename , line ); 624*10671Speter /* 625*10671Speter * on non-local goto, setjmp returns with address to 626*10671Speter * be branched to. 627*10671Speter */ 628*10671Speter putprintf( " jmp (r0)" , 0 ); 629*10671Speter putlab(setjmp0); 630*10671Speter } 631*10671Speter } 632*10671Speter 633*10671Speter fp_exitcode(eecookiep) 634*10671Speter struct entry_exit_cookie *eecookiep; 635*10671Speter { 636*10671Speter /* 637*10671Speter * if there were file variables declared at this level 638*10671Speter * call PCLOSE( ap ) to clean them up. 639*10671Speter */ 640*10671Speter if ( dfiles[ cbn ] ) { 641*10671Speter putleaf( P2ICON , 0 , 0 , ADDTYPE( P2FTN | P2INT , P2PTR ) 642*10671Speter , "_PCLOSE" ); 643*10671Speter putleaf( P2REG , 0 , P2AP , ADDTYPE( P2CHAR , P2PTR ) , 0 ); 644*10671Speter putop( P2CALL , P2INT ); 645*10671Speter putdot( filename , line ); 646*10671Speter } 647*10671Speter /* 648*10671Speter * if this is a function, 649*10671Speter * the function variable is the return value. 650*10671Speter * if it's a scalar valued function, return scalar, 651*10671Speter * else, return a pointer to the structure value. 652*10671Speter */ 653*10671Speter if ( eecookiep-> nlp -> class == FUNC ) { 654*10671Speter struct nl *fvar = eecookiep-> nlp -> ptr[ NL_FVAR ]; 655*10671Speter long fvartype = p2type( fvar -> type ); 656*10671Speter long label; 657*10671Speter char labelname[ BUFSIZ ]; 658*10671Speter 659*10671Speter switch ( classify( fvar -> type ) ) { 660*10671Speter case TBOOL: 661*10671Speter case TCHAR: 662*10671Speter case TINT: 663*10671Speter case TSCAL: 664*10671Speter case TDOUBLE: 665*10671Speter case TPTR: 666*10671Speter putRV( fvar -> symbol , ( fvar -> nl_block ) & 037 , 667*10671Speter fvar -> value[ NL_OFFS ] , 668*10671Speter fvar -> extra_flags , 669*10671Speter fvartype ); 670*10671Speter break; 671*10671Speter default: 672*10671Speter label = getlab(); 673*10671Speter sprintf( labelname , PREFIXFORMAT , LABELPREFIX , label ); 674*10671Speter putprintf( " .data" , 0 ); 675*10671Speter aligndot(A_STRUCT); 676*10671Speter putprintf( " .lcomm %s,%d" , 0 , 677*10671Speter labelname , lwidth( fvar -> type ) ); 678*10671Speter putprintf( " .text" , 0 ); 679*10671Speter putleaf( P2NAME , 0 , 0 , fvartype , labelname ); 680*10671Speter putLV( fvar -> symbol , ( fvar -> nl_block ) & 037 , 681*10671Speter fvar -> value[ NL_OFFS ] , 682*10671Speter fvar -> extra_flags , 683*10671Speter fvartype ); 684*10671Speter putstrop( P2STASG , fvartype , lwidth( fvar -> type ) , 685*10671Speter align( fvar -> type ) ); 686*10671Speter putdot( filename , line ); 687*10671Speter putleaf( P2ICON , 0 , 0 , fvartype , labelname ); 688*10671Speter break; 689*10671Speter } 690*10671Speter putop( P2FORCE , fvartype ); 691*10671Speter putdot( filename , line ); 692*10671Speter } 693*10671Speter /* 694*10671Speter * if there are nested procedures we must save the display. 695*10671Speter */ 696*10671Speter if ( parts[ cbn ] & NONLOCALVAR ) { 697*10671Speter /* 698*10671Speter * restore old display entry from save area 699*10671Speter */ 700*10671Speter putprintf( " movq %d(%s),%s+%d" , 0 701*10671Speter , DSAVEOFFSET , P2FPNAME 702*10671Speter , DISPLAYNAME , cbn * sizeof(struct dispsave) ); 703*10671Speter } 704*10671Speter } 705*10671Speter 706*10671Speter fp_epilogue(eecookiep) 707*10671Speter struct entry_exit_cookie *eecookiep; 708*10671Speter { 709*10671Speter putprintf(" ret" , 0 ); 710*10671Speter /* 711*10671Speter * set the register save mask. 712*10671Speter */ 713*10671Speter putprintf(" .set %s%d,0x%x", 0, 714*10671Speter SAVE_MASK_LABEL, eecookiep -> savlabel, savmask()); 715*10671Speter } 716*10671Speter 717*10671Speter fp_formalentry(eecookiep) 718*10671Speter struct entry_exit_cookie *eecookiep; 719*10671Speter { 720*10671Speter 721*10671Speter putprintf("%s%s:" , 0 , FORMALPREFIX , eecookiep -> extname ); 722*10671Speter putprintf(" .word %s%d", 0, SAVE_MASK_LABEL, eecookiep -> savlabel ); 723*10671Speter putleaf( P2ICON , 0 , 0 , ADDTYPE( P2FTN | P2INT , P2PTR ) , "_FCALL" ); 724*10671Speter putRV( 0 , cbn , 725*10671Speter eecookiep -> nlp -> value[ NL_OFFS ] + sizeof( struct formalrtn * ) , 726*10671Speter NPARAM , P2PTR | P2STRTY ); 727*10671Speter putRV(0, cbn, eecookiep -> nlp -> value[NL_OFFS], NPARAM, P2PTR|P2STRTY); 728*10671Speter putop( P2LISTOP , P2INT ); 729*10671Speter putop( P2CALL , P2INT ); 730*10671Speter putdot( filename , line ); 731*10671Speter putjbr( eecookiep -> toplabel ); 732*10671Speter } 733*10671Speter #endif vax 734*10671Speter 735*10671Speter #ifdef mc68000 736*10671Speter 737*10671Speter codeformain() 738*10671Speter { 739*10671Speter putprintf(" .text", 0); 740*10671Speter putprintf(" .globl _main", 0); 741*10671Speter putprintf("_main:", 0); 742*10671Speter putprintf(" link %s,#0", 0, P2FPNAME); 743*10671Speter if (opt('t')) { 744*10671Speter putprintf(" pea 1", 0); 745*10671Speter } else { 746*10671Speter putprintf(" pea 0", 0); 747*10671Speter } 748*10671Speter putprintf(" jbsr _PCSTART", 0); 749*10671Speter putprintf(" addql #4,sp", 0); 750*10671Speter putprintf(" movl %s@(8),__argc", 0, P2FPNAME); 751*10671Speter putprintf(" movl %s@(12),__argv", 0, P2FPNAME); 752*10671Speter putprintf(" jbsr _program", 0); 753*10671Speter putprintf(" pea 0", 0); 754*10671Speter putprintf(" jbsr _PCEXIT", 0); 755*10671Speter } 756*10671Speter 757*10671Speter prog_prologue(eecookiep) 758*10671Speter struct entry_exit_cookie *eecookiep; 759*10671Speter { 760*10671Speter int ftnno = eecookiep -> nlp -> value[NL_ENTLOC]; 761*10671Speter 762*10671Speter putprintf(" .text", 0); 763*10671Speter putprintf(" .globl _program", 0); 764*10671Speter putprintf("_program:", 0); 765*10671Speter putprintf(" link %s,#0", 0, P2FPNAME); 766*10671Speter putprintf(" addl #-%s%d,sp", 0, FRAME_SIZE_LABEL, ftnno); 767*10671Speter /* touch new end of stack, to break more stack space */ 768*10671Speter putprintf(" tstb sp@(-%s%d)", 0, PAGE_BREAK_LABEL, ftnno); 769*10671Speter putprintf(" moveml #%s%d,sp@", 0, SAVE_MASK_LABEL, ftnno); 770*10671Speter } 771*10671Speter 772*10671Speter fp_prologue(eecookiep) 773*10671Speter struct entry_exit_cookie *eecookiep; 774*10671Speter { 775*10671Speter int ftnno = eecookiep -> nlp -> value[NL_ENTLOC]; 776*10671Speter 777*10671Speter sextname(eecookiep -> extname, eecookiep -> nlp -> symbol, cbn - 1); 778*10671Speter putprintf(" .text", 0); 779*10671Speter putprintf(" .globl %s%s", 0, FORMALPREFIX, eecookiep -> extname); 780*10671Speter putprintf(" .globl %s", 0, eecookiep -> extname); 781*10671Speter putprintf("%s:", 0, eecookiep -> extname); 782*10671Speter putprintf(" link %s,#0", 0, P2FPNAME); 783*10671Speter putprintf(" addl #-%s%d,sp", 0, FRAME_SIZE_LABEL, ftnno); 784*10671Speter /* touch new end of stack, to break more stack space */ 785*10671Speter putprintf(" tstb sp@(-%s%d)", 0, PAGE_BREAK_LABEL, ftnno); 786*10671Speter putprintf(" moveml #%s%d,sp@", 0, SAVE_MASK_LABEL, ftnno); 787*10671Speter } 788*10671Speter 789*10671Speter fp_entrycode(eecookiep) 790*10671Speter struct entry_exit_cookie *eecookiep; 791*10671Speter { 792*10671Speter int proflabel = getlab(); 793*10671Speter int setjmp0 = getlab(); 794*10671Speter 795*10671Speter /* 796*10671Speter * fill in the label cookie 797*10671Speter */ 798*10671Speter eecookiep -> toplabel = getlab(); 799*10671Speter putlab(eecookiep -> toplabel); 800*10671Speter /* 801*10671Speter * call mcount if we are profiling. 802*10671Speter */ 803*10671Speter if ( profflag ) { 804*10671Speter putprintf(" movl #%s%d,a0", 0, LABELPREFIX, proflabel); 805*10671Speter putprintf(" jsr mcount", 0); 806*10671Speter putprintf(" .data", 0); 807*10671Speter putprintf(" .even", 0); 808*10671Speter putlab(proflabel); 809*10671Speter putprintf(" .long 0", 0); 810*10671Speter putprintf(" .text", 0); 811*10671Speter } 812*10671Speter /* 813*10671Speter * if there are nested procedures that access our variables 814*10671Speter * we must save the display 815*10671Speter */ 816*10671Speter if (parts[cbn] & NONLOCALVAR) { 817*10671Speter /* 818*10671Speter * save the old display 819*10671Speter */ 820*10671Speter putprintf(" movl %s+%d,%s@(%d)", 0, 821*10671Speter DISPLAYNAME, cbn * sizeof(struct dispsave), 822*10671Speter P2FPNAME, DSAVEOFFSET); 823*10671Speter /* 824*10671Speter * set up the new display by saving the framepointer 825*10671Speter * in the display structure. 826*10671Speter */ 827*10671Speter putprintf(" movl %s,%s+%d", 0, 828*10671Speter P2FPNAME, DISPLAYNAME, cbn * sizeof(struct dispsave)); 829*10671Speter } 830*10671Speter /* 831*10671Speter * zero local variables if checking is on 832*10671Speter * by calling blkclr( bytes of locals , starting local address ); 833*10671Speter */ 834*10671Speter if ( opt( 't' ) && ( -sizes[ cbn ].om_max ) > DPOFF1 ) { 835*10671Speter putleaf( P2ICON , 0 , 0 , ADDTYPE( P2FTN | P2INT , P2PTR ) 836*10671Speter , "_blkclr" ); 837*10671Speter putLV( 0 , cbn , sizes[ cbn ].om_max , NLOCAL , P2CHAR ); 838*10671Speter putleaf( P2ICON , ( -sizes[ cbn ].om_max ) - DPOFF1 839*10671Speter , 0 , P2INT , 0 ); 840*10671Speter putop( P2LISTOP , P2INT ); 841*10671Speter putop( P2CALL , P2INT ); 842*10671Speter putdot( filename , line ); 843*10671Speter } 844*10671Speter /* 845*10671Speter * set up goto vector if non-local goto to this frame 846*10671Speter */ 847*10671Speter if ( parts[ cbn ] & NONLOCALGOTO ) { 848*10671Speter putleaf( P2ICON , 0 , 0 , ADDTYPE( P2FTN | P2INT , P2PTR ) 849*10671Speter , "_setjmp" ); 850*10671Speter putLV( 0 , cbn , GOTOENVOFFSET , NLOCAL , P2PTR|P2STRTY ); 851*10671Speter putop( P2CALL , P2INT ); 852*10671Speter putleaf( P2ICON , 0 , 0 , P2INT , 0 ); 853*10671Speter putop( P2NE , P2INT ); 854*10671Speter putleaf( P2ICON , setjmp0 , 0 , P2INT , 0 ); 855*10671Speter putop( P2CBRANCH , P2INT ); 856*10671Speter putdot( filename , line ); 857*10671Speter /* 858*10671Speter * on non-local goto, setjmp returns with address to 859*10671Speter * be branched to. 860*10671Speter */ 861*10671Speter putprintf(" movl d0,a0", 0); 862*10671Speter putprintf(" jmp a0@", 0); 863*10671Speter putlab(setjmp0); 864*10671Speter } 865*10671Speter } 866*10671Speter 867*10671Speter fp_exitcode(eecookiep) 868*10671Speter struct entry_exit_cookie *eecookiep; 869*10671Speter { 870*10671Speter /* 871*10671Speter * if there were file variables declared at this level 872*10671Speter * call PCLOSE( ap ) to clean them up. 873*10671Speter */ 874*10671Speter if ( dfiles[ cbn ] ) { 875*10671Speter putleaf( P2ICON , 0 , 0 , ADDTYPE( P2FTN | P2INT , P2PTR ) 876*10671Speter , "_PCLOSE" ); 877*10671Speter putleaf( P2REG , 0 , P2AP , ADDTYPE( P2CHAR , P2PTR ) , 0 ); 878*10671Speter putop( P2CALL , P2INT ); 879*10671Speter putdot( filename , line ); 880*10671Speter } 881*10671Speter /* 882*10671Speter * if this is a function, 883*10671Speter * the function variable is the return value. 884*10671Speter * if it's a scalar valued function, return scalar, 885*10671Speter * else, return a pointer to the structure value. 886*10671Speter */ 887*10671Speter if ( eecookiep -> nlp -> class == FUNC ) { 888*10671Speter struct nl *fvar = eecookiep -> nlp -> ptr[ NL_FVAR ]; 889*10671Speter long fvartype = p2type( fvar -> type ); 890*10671Speter long label; 891*10671Speter char labelname[ BUFSIZ ]; 892*10671Speter 893*10671Speter switch ( classify( fvar -> type ) ) { 894*10671Speter case TBOOL: 895*10671Speter case TCHAR: 896*10671Speter case TINT: 897*10671Speter case TSCAL: 898*10671Speter case TDOUBLE: 899*10671Speter case TPTR: 900*10671Speter putRV( fvar -> symbol , ( fvar -> nl_block ) & 037 , 901*10671Speter fvar -> value[ NL_OFFS ] , 902*10671Speter fvar -> extra_flags , 903*10671Speter fvartype ); 904*10671Speter break; 905*10671Speter default: 906*10671Speter label = getlab(); 907*10671Speter sprintf( labelname , PREFIXFORMAT , LABELPREFIX , label ); 908*10671Speter putprintf(" .lcomm %s,%d", 0, 909*10671Speter labelname, lwidth(fvar -> type)); 910*10671Speter putleaf( P2NAME , 0 , 0 , fvartype , labelname ); 911*10671Speter putLV( fvar -> symbol , ( fvar -> nl_block ) & 037 , 912*10671Speter fvar -> value[ NL_OFFS ] , 913*10671Speter fvar -> extra_flags , 914*10671Speter fvartype ); 915*10671Speter putstrop( P2STASG , fvartype , lwidth( fvar -> type ) , 916*10671Speter align( fvar -> type ) ); 917*10671Speter putdot( filename , line ); 918*10671Speter putleaf( P2ICON , 0 , 0 , fvartype , labelname ); 919*10671Speter break; 920*10671Speter } 921*10671Speter putop( P2FORCE , fvartype ); 922*10671Speter putdot( filename , line ); 923*10671Speter } 924*10671Speter /* 925*10671Speter * if we saved a display, we must restore it. 926*10671Speter */ 927*10671Speter if ( parts[ cbn ] & NONLOCALVAR ) { 928*10671Speter /* 929*10671Speter * restore old display entry from save area 930*10671Speter */ 931*10671Speter putprintf(" movl %s@(%d),%s+%d", 0, 932*10671Speter P2FPNAME, DSAVEOFFSET, 933*10671Speter DISPLAYNAME, cbn * sizeof(struct dispsave)); 934*10671Speter } 935*10671Speter } 936*10671Speter 937*10671Speter fp_epilogue(eecookiep) 938*10671Speter struct entry_exit_cookie *eecookiep; 939*10671Speter { 940*10671Speter /* 941*10671Speter * all done by the second pass. 942*10671Speter */ 943*10671Speter } 944*10671Speter 945*10671Speter fp_formalentry(eecookiep) 946*10671Speter struct entry_exit_cookie *eecookiep; 947*10671Speter { 948*10671Speter putprintf( "%s%s:" , 0 , FORMALPREFIX , eecookiep -> extname ); 949*10671Speter putprintf(" link %s,#0", 0, P2FPNAME); 950*10671Speter putprintf(" addl #-%s%d,sp", 0, FRAME_SIZE_LABEL, ftnno); 951*10671Speter /* touch new end of stack, to break more stack space */ 952*10671Speter putprintf(" tstb sp@(-%s%d)", 0, PAGE_BREAK_LABEL, ftnno); 953*10671Speter putprintf(" moveml #%s%d,sp@", 0, SAVE_MASK_LABEL, ftnno); 954*10671Speter putleaf( P2ICON , 0 , 0 , ADDTYPE( P2FTN | P2INT , P2PTR ) , "_FCALL" ); 955*10671Speter putRV( 0 , cbn , 956*10671Speter eecookiep -> nlp -> value[ NL_OFFS ] + sizeof( struct formalrtn * ) , 957*10671Speter NPARAM , P2PTR | P2STRTY ); 958*10671Speter putRV(0, cbn, eecookiep -> nlp -> value[NL_OFFS], NPARAM, P2PTR|P2STRTY); 959*10671Speter putop( P2LISTOP , P2INT ); 960*10671Speter putop( P2CALL , P2INT ); 961*10671Speter putdot( filename , line ); 962*10671Speter putjbr( eecookiep -> toplabel ); 963*10671Speter } 964*10671Speter #endif mc68000 9653363Speter #endif PC 966