13192Smckusick /* Copyright (c) 1979 Regents of the University of California */ 23192Smckusick 3*18346Smckusick static char sccsid[] = "@(#)fend.c 1.22.1.1 03/15/85"; 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" 1111337Speter #include "tmps.h" 123192Smckusick 133192Smckusick /* 143192Smckusick * this array keeps the pxp counters associated with 153192Smckusick * functions and procedures, so that they can be output 163192Smckusick * when their bodies are encountered 173192Smckusick */ 183192Smckusick int bodycnts[ DSPLYSZ ]; 193192Smckusick 203192Smckusick #ifdef PC 213192Smckusick # include "pc.h" 223192Smckusick # include "pcops.h" 233192Smckusick #endif PC 243192Smckusick 253192Smckusick #ifdef OBJ 263192Smckusick int cntpatch; 273192Smckusick int nfppatch; 283192Smckusick #endif OBJ 293192Smckusick 303192Smckusick struct nl *Fp; 313192Smckusick int pnumcnt; 323192Smckusick /* 333192Smckusick * Funcend is called to 343192Smckusick * finish a block by generating 353192Smckusick * the code for the statements. 363192Smckusick * It then looks for unresolved declarations 373192Smckusick * of labels, procedures and functions, 383192Smckusick * and cleans up the name list. 393192Smckusick * For the program, it checks the 403192Smckusick * semantics of the program 413192Smckusick * statement (yuchh). 423192Smckusick */ 433192Smckusick funcend(fp, bundle, endline) 443192Smckusick struct nl *fp; 45*18346Smckusick int *bundle; 463192Smckusick int endline; 473192Smckusick { 483192Smckusick register struct nl *p; 493192Smckusick register int i, b; 50*18346Smckusick int var, inp, out, *blk; 513192Smckusick bool chkref; 523192Smckusick struct nl *iop; 533192Smckusick char *cp; 543192Smckusick extern int cntstat; 553192Smckusick # ifdef PC 5610671Speter struct entry_exit_cookie eecookie; 573192Smckusick # endif PC 583192Smckusick 593192Smckusick cntstat = 0; 603192Smckusick /* 613192Smckusick * yyoutline(); 623192Smckusick */ 633192Smckusick if (program != NIL) 643192Smckusick line = program->value[3]; 65*18346Smckusick blk = bundle[2]; 663192Smckusick if (fp == NIL) { 673192Smckusick cbn--; 683192Smckusick # ifdef PTREE 693192Smckusick nesting--; 703192Smckusick # endif PTREE 713192Smckusick return; 723192Smckusick } 733192Smckusick #ifdef OBJ 743192Smckusick /* 753192Smckusick * Patch the branch to the 763192Smckusick * entry point of the function 773192Smckusick */ 78*18346Smckusick patch4(fp->value[NL_ENTLOC]); 793192Smckusick /* 803192Smckusick * Put out the block entrance code and the block name. 813192Smckusick * HDRSZE is the number of bytes of info in the static 823192Smckusick * BEG data area exclusive of the proc name. It is 833192Smckusick * currently defined as: 843192Smckusick /* struct hdr { 853192Smckusick /* long framesze; /* number of bytes of local vars */ 863192Smckusick /* long nargs; /* number of bytes of arguments */ 873192Smckusick /* bool tests; /* TRUE => perform runtime tests */ 883192Smckusick /* short offset; /* offset of procedure in source file */ 893192Smckusick /* char name[1]; /* name of active procedure */ 903192Smckusick /* }; 913192Smckusick */ 923192Smckusick # define HDRSZE (2 * sizeof(long) + sizeof(short) + sizeof(bool)) 933192Smckusick var = put(2, ((lenstr(fp->symbol,0) + HDRSZE) << 8) 943192Smckusick | (cbn == 1 && opt('p') == 0 ? O_NODUMP: O_BEG), (long)0); 953192Smckusick /* 963192Smckusick * output the number of bytes of arguments 973192Smckusick * this is only checked on formal calls. 983192Smckusick */ 99*18346Smckusick put(2, O_CASE4, cbn == 1 ? (long)0 : (long)(fp->value[NL_OFFS]-DPOFF2)); 1003192Smckusick /* 1013192Smckusick * Output the runtime test mode for the routine 1023192Smckusick */ 103*18346Smckusick put(2, sizeof(bool) == 2 ? O_CASE2 : O_CASE4, opt('t') ? TRUE : FALSE); 1043192Smckusick /* 1053192Smckusick * Output line number and routine name 1063192Smckusick */ 107*18346Smckusick put(2, O_CASE2, bundle[1]); 1083192Smckusick putstr(fp->symbol, 0); 1093192Smckusick #endif OBJ 1103192Smckusick #ifdef PC 1113192Smckusick /* 1123192Smckusick * put out the procedure entry code 1133192Smckusick */ 11410671Speter eecookie.nlp = fp; 1153192Smckusick if ( fp -> class == PROG ) { 1169129Smckusick /* 1179129Smckusick * If there is a label declaration in the main routine 1189129Smckusick * then there may be a non-local goto to it that does 1199129Smckusick * not appear in this module. We have to assume that 1209129Smckusick * such a reference may occur and generate code to 1219129Smckusick * prepare for it. 1229129Smckusick */ 1239129Smckusick if ( parts[ cbn ] & LPRT ) { 1249129Smckusick parts[ cbn ] |= ( NONLOCALVAR | NONLOCALGOTO ); 1259129Smckusick } 12610671Speter codeformain(); 1277917Smckusick ftnno = fp -> value[NL_ENTLOC]; 12810671Speter prog_prologue(&eecookie); 129*18346Smckusick stabline(bundle[1]); 130*18346Smckusick stabfunc(fp, "program", bundle[1] , 0 ); 1313192Smckusick } else { 1327917Smckusick ftnno = fp -> value[NL_ENTLOC]; 13310671Speter fp_prologue(&eecookie); 134*18346Smckusick stabline(bundle[1]); 135*18346Smckusick stabfunc(fp, fp->symbol, bundle[1], cbn - 1); 1363192Smckusick for ( p = fp -> chain ; p != NIL ; p = p -> chain ) { 137*18346Smckusick stabparam(p, p->value[NL_OFFS], lwidth(p->type)); 1383192Smckusick } 1393192Smckusick if ( fp -> class == FUNC ) { 1403192Smckusick /* 1413192Smckusick * stab the function variable 1423192Smckusick */ 1433192Smckusick p = fp -> ptr[ NL_FVAR ]; 144*18346Smckusick stablvar(p, p->value[NL_OFFS], lwidth(p->type)); 1453192Smckusick } 1463192Smckusick /* 1473192Smckusick * stab local variables 1483192Smckusick * rummage down hash chain links. 1493192Smckusick */ 1503192Smckusick for ( i = 0 ; i <= 077 ; i++ ) { 1513192Smckusick for ( p = disptab[ i ] ; p != NIL ; p = p->nl_next) { 1523192Smckusick if ( ( p -> nl_block & 037 ) != cbn ) { 1533192Smckusick break; 1543192Smckusick } 1553192Smckusick /* 156*18346Smckusick * stab locals (not parameters) 1573192Smckusick */ 158*18346Smckusick if (p->symbol != NIL) { 159*18346Smckusick if (p->class == VAR && p->value[NL_OFFS] < 0) { 160*18346Smckusick stablvar(p, p->value[NL_OFFS], lwidth(p->type)); 161*18346Smckusick } else if (p->class == CONST) { 162*18346Smckusick stabconst(p); 163*18346Smckusick } 1643192Smckusick } 1653192Smckusick } 1663192Smckusick } 1673192Smckusick } 1683192Smckusick stablbrac( cbn ); 1693192Smckusick /* 1703192Smckusick * ask second pass to allocate known locals 1713192Smckusick */ 17211337Speter putlbracket(ftnno, &sizes[cbn]); 17310671Speter fp_entrycode(&eecookie); 1743192Smckusick #endif PC 1753192Smckusick if ( monflg ) { 1763192Smckusick if ( fp -> value[ NL_CNTR ] != 0 ) { 1773192Smckusick inccnt( fp -> value [ NL_CNTR ] ); 1783192Smckusick } 1793192Smckusick inccnt( bodycnts[ fp -> nl_block & 037 ] ); 1803192Smckusick } 1813192Smckusick if (fp->class == PROG) { 1823192Smckusick /* 1833192Smckusick * The glorious buffers option. 1843192Smckusick * 0 = don't buffer output 1853192Smckusick * 1 = line buffer output 1863192Smckusick * 2 = 512 byte buffer output 1873192Smckusick */ 1883192Smckusick # ifdef OBJ 1893192Smckusick if (opt('b') != 1) 190*18346Smckusick put(1, O_BUFF | opt('b') << 8); 1913192Smckusick # endif OBJ 1923192Smckusick # ifdef PC 1933192Smckusick if ( opt( 'b' ) != 1 ) { 1943192Smckusick putleaf( P2ICON , 0 , 0 1953192Smckusick , ADDTYPE( P2FTN | P2INT , P2PTR ) , "_BUFF" ); 196*18346Smckusick putleaf( P2ICON , opt( 'b' ) , 0 , P2INT , 0 ); 1973192Smckusick putop( P2CALL , P2INT ); 1983192Smckusick putdot( filename , line ); 1993192Smckusick } 2003192Smckusick # endif PC 2017953Speter inp = 0; 2023192Smckusick out = 0; 2033192Smckusick for (p = fp->chain; p != NIL; p = p->chain) { 204*18346Smckusick if (strcmp(p->symbol, input->symbol) == 0) { 2053192Smckusick inp++; 2063192Smckusick continue; 2073192Smckusick } 208*18346Smckusick if (strcmp(p->symbol, output->symbol) == 0) { 2093192Smckusick out++; 2103192Smckusick continue; 2113192Smckusick } 2123192Smckusick iop = lookup1(p->symbol); 2133192Smckusick if (iop == NIL || bn != cbn) { 2143192Smckusick error("File %s listed in program statement but not declared", p->symbol); 2153192Smckusick continue; 2163192Smckusick } 2173192Smckusick if (iop->class != VAR) { 2183192Smckusick error("File %s listed in program statement but declared as a %s", p->symbol, classes[iop->class]); 2193192Smckusick continue; 2203192Smckusick } 2213192Smckusick if (iop->type == NIL) 2223192Smckusick continue; 2233192Smckusick if (iop->type->class != FILET) { 2243192Smckusick error("File %s listed in program statement but defined as %s", 2253192Smckusick p->symbol, nameof(iop->type)); 2263192Smckusick continue; 2273192Smckusick } 2283192Smckusick # ifdef OBJ 229*18346Smckusick put(2, O_CON24, text(iop->type) ? 0 : width(iop->type->type)); 2303192Smckusick i = lenstr(p->symbol,0); 231*18346Smckusick put(2, O_CON24, i); 232*18346Smckusick put(2, O_LVCON, i); 2333192Smckusick putstr(p->symbol, 0); 234*18346Smckusick put(2, O_LV | bn<<8+INDX, (int)iop->value[NL_OFFS]); 235*18346Smckusick put(1, O_DEFNAME); 2363192Smckusick # endif OBJ 2373192Smckusick # ifdef PC 2383192Smckusick putleaf( P2ICON , 0 , 0 2393192Smckusick , ADDTYPE( P2FTN | P2INT , P2PTR ) 2403192Smckusick , "_DEFNAME" ); 2413837Speter putLV( p -> symbol , bn , iop -> value[NL_OFFS] , 2423837Speter iop -> extra_flags , p2type( iop ) ); 2433192Smckusick putCONG( p -> symbol , strlen( p -> symbol ) 2443192Smckusick , LREQ ); 2453192Smckusick putop( P2LISTOP , P2INT ); 2463192Smckusick putleaf( P2ICON , strlen( p -> symbol ) 247*18346Smckusick , 0 , P2INT , 0 ); 2483192Smckusick putop( P2LISTOP , P2INT ); 2493192Smckusick putleaf( P2ICON 2503192Smckusick , text(iop->type) ? 0 : width(iop->type->type) 251*18346Smckusick , 0 , P2INT , 0 ); 2523192Smckusick putop( P2LISTOP , P2INT ); 2533192Smckusick putop( P2CALL , P2INT ); 2543192Smckusick putdot( filename , line ); 2553192Smckusick # endif PC 2563192Smckusick } 2573192Smckusick } 2583192Smckusick /* 2593192Smckusick * Process the prog/proc/func body 2603192Smckusick */ 261*18346Smckusick noreach = 0; 262*18346Smckusick line = bundle[1]; 2633192Smckusick statlist(blk); 2643192Smckusick # ifdef PTREE 2653192Smckusick { 2663192Smckusick pPointer Body = tCopy( blk ); 2673192Smckusick 2683192Smckusick pDEF( PorFHeader[ nesting -- ] ).PorFBody = Body; 2693192Smckusick } 2703192Smckusick # endif PTREE 2713192Smckusick # ifdef OBJ 272*18346Smckusick if (cbn== 1 && monflg != 0) { 273*18346Smckusick patchfil(cntpatch - 2, (long)cnts, 2); 274*18346Smckusick patchfil(nfppatch - 2, (long)pfcnt, 2); 2753192Smckusick } 2763192Smckusick # endif OBJ 2773192Smckusick # ifdef PC 2783192Smckusick if ( fp -> class == PROG && monflg ) { 2793192Smckusick putleaf( P2ICON , 0 , 0 , ADDTYPE( P2FTN | P2INT , P2PTR ) 2803192Smckusick , "_PMFLUSH" ); 281*18346Smckusick putleaf( P2ICON , cnts , 0 , P2INT , 0 ); 282*18346Smckusick putleaf( P2ICON , pfcnt , 0 , P2INT , 0 ); 2833192Smckusick putop( P2LISTOP , P2INT ); 2843837Speter putLV( PCPCOUNT , 0 , 0 , NGLOBAL , P2INT ); 2853192Smckusick putop( P2LISTOP , P2INT ); 2863192Smckusick putop( P2CALL , P2INT ); 2873192Smckusick putdot( filename , line ); 2883192Smckusick } 2893192Smckusick # endif PC 2907953Speter /* 2917953Speter * Clean up the symbol table displays and check for unresolves 2927953Speter */ 2937953Speter line = endline; 2943192Smckusick if (fp->class == PROG && inp == 0 && (input->nl_flags & (NUSED|NMOD)) != 0) { 2953192Smckusick recovered(); 2963192Smckusick error("Input is used but not defined in the program statement"); 2973192Smckusick } 2987953Speter if (fp->class == PROG && out == 0 && (output->nl_flags & (NUSED|NMOD)) != 0) { 2997953Speter recovered(); 3007953Speter error("Output is used but not defined in the program statement"); 3017953Speter } 3023192Smckusick b = cbn; 3033192Smckusick Fp = fp; 304*18346Smckusick chkref = syneflg == errcnt[cbn] && opt('w') == 0; 3053192Smckusick for (i = 0; i <= 077; i++) { 3063192Smckusick for (p = disptab[i]; p != NIL && (p->nl_block & 037) == b; p = p->nl_next) { 3073192Smckusick /* 3083192Smckusick * Check for variables defined 3093192Smckusick * but not referenced 3103192Smckusick */ 3113192Smckusick if (chkref && p->symbol != NIL) 3123192Smckusick switch (p->class) { 3133192Smckusick case FIELD: 3143192Smckusick /* 3153192Smckusick * If the corresponding record is 3163192Smckusick * unused, we shouldn't complain about 3173192Smckusick * the fields. 3183192Smckusick */ 3193192Smckusick default: 3203192Smckusick if ((p->nl_flags & (NUSED|NMOD)) == 0) { 3213192Smckusick warning(); 3223192Smckusick nerror("%s %s is neither used nor set", classes[p->class], p->symbol); 3233192Smckusick break; 3243192Smckusick } 3253192Smckusick /* 3263192Smckusick * If a var parameter is either 3273192Smckusick * modified or used that is enough. 3283192Smckusick */ 3293192Smckusick if (p->class == REF) 3303192Smckusick continue; 3313192Smckusick # ifdef OBJ 3323192Smckusick if ((p->nl_flags & NUSED) == 0) { 3333192Smckusick warning(); 3343192Smckusick nerror("%s %s is never used", classes[p->class], p->symbol); 3353192Smckusick break; 3363192Smckusick } 3373192Smckusick # endif OBJ 3383192Smckusick # ifdef PC 3393837Speter if (((p->nl_flags & NUSED) == 0) && ((p->extra_flags & NEXTERN) == 0)) { 3403192Smckusick warning(); 3413192Smckusick nerror("%s %s is never used", classes[p->class], p->symbol); 3423192Smckusick break; 3433192Smckusick } 3443192Smckusick # endif PC 3453192Smckusick if ((p->nl_flags & NMOD) == 0) { 3463192Smckusick warning(); 3473192Smckusick nerror("%s %s is used but never set", classes[p->class], p->symbol); 3483192Smckusick break; 3493192Smckusick } 3503192Smckusick case LABEL: 3513192Smckusick case FVAR: 3523192Smckusick case BADUSE: 3533192Smckusick break; 3543192Smckusick } 3553192Smckusick switch (p->class) { 3563192Smckusick case BADUSE: 3573192Smckusick cp = "s"; 358*18346Smckusick if (p->chain->ud_next == NIL) 3593192Smckusick cp++; 3603192Smckusick eholdnl(); 3613192Smckusick if (p->value[NL_KINDS] & ISUNDEF) 3623192Smckusick nerror("%s undefined on line%s", p->symbol, cp); 3633192Smckusick else 3643192Smckusick nerror("%s improperly used on line%s", p->symbol, cp); 3653192Smckusick pnumcnt = 10; 366*18346Smckusick pnums(p->chain); 3673192Smckusick pchr('\n'); 3683192Smckusick break; 3693192Smckusick 3703192Smckusick case FUNC: 3713192Smckusick case PROC: 3723192Smckusick # ifdef OBJ 3733192Smckusick if ((p->nl_flags & NFORWD)) 3743192Smckusick nerror("Unresolved forward declaration of %s %s", classes[p->class], p->symbol); 3753192Smckusick # endif OBJ 3763192Smckusick # ifdef PC 3773837Speter if ((p->nl_flags & NFORWD) && ((p->extra_flags & NEXTERN) == 0)) 3783192Smckusick nerror("Unresolved forward declaration of %s %s", classes[p->class], p->symbol); 3793192Smckusick # endif PC 3803192Smckusick break; 3813192Smckusick 3823192Smckusick case LABEL: 3833192Smckusick if (p->nl_flags & NFORWD) 3843192Smckusick nerror("label %s was declared but not defined", p->symbol); 3853192Smckusick break; 3863192Smckusick case FVAR: 3873192Smckusick if ((p->nl_flags & NMOD) == 0) 3883192Smckusick nerror("No assignment to the function variable"); 3893192Smckusick break; 3903192Smckusick } 3913192Smckusick } 3923192Smckusick /* 3933192Smckusick * Pop this symbol 3943192Smckusick * table slot 3953192Smckusick */ 3963192Smckusick disptab[i] = p; 3973192Smckusick } 3983192Smckusick 3993192Smckusick # ifdef OBJ 400*18346Smckusick put(1, O_END); 4013192Smckusick # endif OBJ 4023192Smckusick # ifdef PC 40310671Speter fp_exitcode(&eecookie); 40410671Speter stabrbrac(cbn); 40510671Speter putrbracket(ftnno); 40610671Speter fp_epilogue(&eecookie); 40710671Speter if (fp -> class != PROG) { 40810671Speter fp_formalentry(&eecookie); 4093192Smckusick } 4103192Smckusick /* 4113192Smckusick * declare pcp counters, if any 4123192Smckusick */ 4133192Smckusick if ( monflg && fp -> class == PROG ) { 4143192Smckusick putprintf( " .data" , 0 ); 41510671Speter aligndot(P2INT); 4163192Smckusick putprintf( " .comm " , 1 ); 4173192Smckusick putprintf( PCPCOUNT , 1 ); 4183192Smckusick putprintf( ",%d" , 0 , ( cnts + 1 ) * sizeof (long) ); 4193192Smckusick putprintf( " .text" , 0 ); 4203192Smckusick } 4213192Smckusick # endif PC 4223192Smckusick #ifdef DEBUG 423*18346Smckusick dumpnl(fp->ptr[2], fp->symbol); 4243192Smckusick #endif 4255654Slinton 4265654Slinton #ifdef OBJ 4273192Smckusick /* 4285654Slinton * save the namelist for the debugger pdx 4295654Slinton */ 4305654Slinton 431*18346Smckusick savenl(fp->ptr[2], fp->symbol); 4325654Slinton #endif 4335654Slinton 4345654Slinton /* 4353192Smckusick * Restore the 4363192Smckusick * (virtual) name list 4373192Smckusick * position 4383192Smckusick */ 4393192Smckusick nlfree(fp->ptr[2]); 4403192Smckusick /* 4413192Smckusick * Proc/func has been 4423192Smckusick * resolved 4433192Smckusick */ 4443192Smckusick fp->nl_flags &= ~NFORWD; 4453192Smckusick /* 4463192Smckusick * Patch the beg 4473192Smckusick * of the proc/func to 4483192Smckusick * the proper variable size 4493192Smckusick */ 4503192Smckusick if (Fp == NIL) 4513192Smckusick elineon(); 4523192Smckusick # ifdef OBJ 453*18346Smckusick patchfil(var, leven(-sizes[cbn].om_max), 2); 4543192Smckusick # endif OBJ 4553192Smckusick cbn--; 4563192Smckusick if (inpflist(fp->symbol)) { 4573192Smckusick opop('l'); 4583192Smckusick } 4593192Smckusick } 4603363Speter 4613363Speter #ifdef PC 4623363Speter /* 4633363Speter * construct the long name of a function based on it's static nesting. 4643363Speter * into a caller-supplied buffer (that should be about BUFSIZ big). 4653363Speter */ 4663363Speter sextname( buffer , name , level ) 4673363Speter char buffer[]; 4683363Speter char *name; 4693363Speter int level; 4703363Speter { 4713363Speter char *starthere; 4723363Speter int i; 4733363Speter 4743363Speter starthere = &buffer[0]; 4753363Speter for ( i = 1 ; i < level ; i++ ) { 4763363Speter sprintf( starthere , EXTFORMAT , enclosing[ i ] ); 4773363Speter starthere += strlen( enclosing[ i ] ) + 1; 4783363Speter } 4793367Speter sprintf( starthere , EXTFORMAT , name ); 4803367Speter starthere += strlen( name ) + 1; 4813363Speter if ( starthere >= &buffer[ BUFSIZ ] ) { 4823363Speter panic( "sextname" ); 4833363Speter } 4843363Speter } 48510671Speter 48610671Speter /* 48710671Speter * code for main() 48810671Speter */ 48910671Speter #ifdef vax 49010671Speter 49110671Speter codeformain() 49210671Speter { 49310671Speter putprintf(" .text" , 0 ); 49410671Speter putprintf(" .align 1" , 0 ); 49510671Speter putprintf(" .globl _main" , 0 ); 49610671Speter putprintf("_main:" , 0 ); 49710671Speter putprintf(" .word 0" , 0 ); 49810671Speter if ( opt ( 't' ) ) { 49910671Speter putprintf(" pushl $1" , 0 ); 50010671Speter } else { 50110671Speter putprintf(" pushl $0" , 0 ); 50210671Speter } 50310671Speter putprintf(" calls $1,_PCSTART" , 0 ); 50410671Speter putprintf(" movl 4(ap),__argc" , 0 ); 50510671Speter putprintf(" movl 8(ap),__argv" , 0 ); 50610671Speter putprintf(" calls $0,_program" , 0 ); 50710671Speter putprintf(" pushl $0" , 0 ); 50810671Speter putprintf(" calls $1,_PCEXIT" , 0 ); 50910671Speter } 51010671Speter 51110671Speter /* 51210671Speter * prologue for the program. 51310671Speter * different because it 51410671Speter * doesn't have formal entry point 51510671Speter */ 51610671Speter prog_prologue(eecookiep) 51710671Speter struct entry_exit_cookie *eecookiep; 51810671Speter { 51910671Speter putprintf(" .text" , 0 ); 52010671Speter putprintf(" .align 1" , 0 ); 52110671Speter putprintf(" .globl _program" , 0 ); 52210671Speter putprintf("_program:" , 0 ); 52310716Speter /* 52410716Speter * register save mask 52510716Speter */ 526*18346Smckusick eecookiep -> savlabel = getlab(); 527*18346Smckusick putprintf(" .word %s%d", 0, SAVE_MASK_LABEL , eecookiep -> savlabel ); 52810671Speter } 52910671Speter 53010671Speter fp_prologue(eecookiep) 53110671Speter struct entry_exit_cookie *eecookiep; 53210671Speter { 533*18346Smckusick int ftnno = eecookiep -> nlp -> value[NL_ENTLOC]; 53410671Speter 53510671Speter sextname( eecookiep -> extname, eecookiep -> nlp -> symbol , cbn - 1 ); 53610671Speter putprintf( " .text" , 0 ); 53710671Speter putprintf( " .align 1" , 0 ); 538*18346Smckusick putprintf( " .globl %s%s", 0, FORMALPREFIX, eecookiep -> extname ); 539*18346Smckusick putprintf( " .globl %s" , 0 , eecookiep -> extname ); 540*18346Smckusick putprintf( "%s:" , 0 , eecookiep -> extname ); 54110671Speter /* 54210671Speter * register save mask 54310671Speter */ 544*18346Smckusick eecookiep -> savlabel = getlab(); 545*18346Smckusick putprintf(" .word %s%d", 0, SAVE_MASK_LABEL , eecookiep -> savlabel ); 54610671Speter } 54710671Speter 54810671Speter /* 54910671Speter * code before any user code. 55010671Speter * or code that is machine dependent. 55110671Speter */ 55210671Speter fp_entrycode(eecookiep) 55310671Speter struct entry_exit_cookie *eecookiep; 55410671Speter { 55510714Speter int ftnno = eecookiep -> nlp -> value[NL_ENTLOC]; 556*18346Smckusick int proflabel = getlab(); 557*18346Smckusick int setjmp0 = getlab(); 55810671Speter 55910671Speter /* 56010671Speter * top of code; destination of jump from formal entry code. 56110671Speter */ 562*18346Smckusick eecookiep -> toplabel = getlab(); 563*18346Smckusick putlab( eecookiep -> toplabel ); 564*18346Smckusick putprintf(" subl2 $%s%d,sp" , 0 , FRAME_SIZE_LABEL, ftnno ); 56510671Speter if ( profflag ) { 56610671Speter /* 56710671Speter * call mcount for profiling 56810671Speter */ 56910671Speter putprintf( " moval " , 1 ); 570*18346Smckusick putprintf( PREFIXFORMAT , 1 , LABELPREFIX , proflabel ); 57110671Speter putprintf( ",r0" , 0 ); 57210671Speter putprintf( " jsb mcount" , 0 ); 57310671Speter putprintf( " .data" , 0 ); 57410671Speter putprintf( " .align 2" , 0 ); 575*18346Smckusick putlab( proflabel ); 57610671Speter putprintf( " .long 0" , 0 ); 57710671Speter putprintf( " .text" , 0 ); 57810671Speter } 57910671Speter /* 58010671Speter * if there are nested procedures that access our variables 58110671Speter * we must save the display. 58210671Speter */ 58310671Speter if ( parts[ cbn ] & NONLOCALVAR ) { 58410671Speter /* 58510671Speter * save old display 58610671Speter */ 58710671Speter putprintf( " movq %s+%d,%d(%s)" , 0 588*18346Smckusick , DISPLAYNAME , cbn * sizeof(struct dispsave) 589*18346Smckusick , DSAVEOFFSET , P2FPNAME ); 59010671Speter /* 59110671Speter * set up new display by saving AP and FP in appropriate 59210671Speter * slot in display structure. 59310671Speter */ 59410671Speter putprintf( " movq %s,%s+%d" , 0 595*18346Smckusick , P2APNAME , DISPLAYNAME , cbn * sizeof(struct dispsave) ); 59610671Speter } 59710671Speter /* 59810671Speter * set underflow checking if runtime tests 59910671Speter */ 60010671Speter if ( opt( 't' ) ) { 60110671Speter putprintf( " bispsw $0xe0" , 0 ); 60210671Speter } 60310671Speter /* 60410671Speter * zero local variables if checking is on 60510671Speter * by calling blkclr( bytes of locals , starting local address ); 60610671Speter */ 60710671Speter if ( opt( 't' ) && ( -sizes[ cbn ].om_max ) > DPOFF1 ) { 60810671Speter putleaf( P2ICON , 0 , 0 , ADDTYPE( P2FTN | P2INT , P2PTR ) 60910671Speter , "_blkclr" ); 610*18346Smckusick putLV( 0 , cbn , sizes[ cbn ].om_max , NLOCAL , P2CHAR ); 611*18346Smckusick putleaf( P2ICON , ( -sizes[ cbn ].om_max ) - DPOFF1 612*18346Smckusick , 0 , P2INT , 0 ); 61310671Speter putop( P2LISTOP , P2INT ); 61410671Speter putop( P2CALL , P2INT ); 61510671Speter putdot( filename , line ); 61610671Speter } 61710671Speter /* 61810671Speter * set up goto vector if non-local goto to this frame 61910671Speter */ 62010671Speter if ( parts[ cbn ] & NONLOCALGOTO ) { 62110671Speter putleaf( P2ICON , 0 , 0 , ADDTYPE( P2FTN | P2INT , P2PTR ) 62210671Speter , "_setjmp" ); 623*18346Smckusick putLV( 0 , cbn , GOTOENVOFFSET , NLOCAL , P2PTR|P2STRTY ); 62410671Speter putop( P2CALL , P2INT ); 625*18346Smckusick putleaf( P2ICON , 0 , 0 , P2INT , 0 ); 62610671Speter putop( P2NE , P2INT ); 627*18346Smckusick putleaf( P2ICON , setjmp0 , 0 , P2INT , 0 ); 62810671Speter putop( P2CBRANCH , P2INT ); 62910671Speter putdot( filename , line ); 63010671Speter /* 63110671Speter * on non-local goto, setjmp returns with address to 63210671Speter * be branched to. 63310671Speter */ 63410671Speter putprintf( " jmp (r0)" , 0 ); 635*18346Smckusick putlab(setjmp0); 63610671Speter } 63710671Speter } 63810671Speter 63910671Speter fp_exitcode(eecookiep) 64010671Speter struct entry_exit_cookie *eecookiep; 64110671Speter { 64210671Speter /* 64310671Speter * if there were file variables declared at this level 64410671Speter * call PCLOSE( ap ) to clean them up. 64510671Speter */ 64610671Speter if ( dfiles[ cbn ] ) { 64710671Speter putleaf( P2ICON , 0 , 0 , ADDTYPE( P2FTN | P2INT , P2PTR ) 64810671Speter , "_PCLOSE" ); 649*18346Smckusick putleaf( P2REG , 0 , P2AP , ADDTYPE( P2CHAR , P2PTR ) , 0 ); 65010671Speter putop( P2CALL , P2INT ); 65110671Speter putdot( filename , line ); 65210671Speter } 65310671Speter /* 65410671Speter * if this is a function, 65510671Speter * the function variable is the return value. 65610671Speter * if it's a scalar valued function, return scalar, 65710671Speter * else, return a pointer to the structure value. 65810671Speter */ 65910671Speter if ( eecookiep-> nlp -> class == FUNC ) { 66010671Speter struct nl *fvar = eecookiep-> nlp -> ptr[ NL_FVAR ]; 66110671Speter long fvartype = p2type( fvar -> type ); 66210671Speter long label; 66310671Speter char labelname[ BUFSIZ ]; 66410671Speter 66510671Speter switch ( classify( fvar -> type ) ) { 66610671Speter case TBOOL: 66710671Speter case TCHAR: 66810671Speter case TINT: 66910671Speter case TSCAL: 67010671Speter case TDOUBLE: 67110671Speter case TPTR: 67210671Speter putRV( fvar -> symbol , ( fvar -> nl_block ) & 037 , 67310671Speter fvar -> value[ NL_OFFS ] , 67410671Speter fvar -> extra_flags , 675*18346Smckusick fvartype ); 676*18346Smckusick putop( P2FORCE , fvartype ); 67710671Speter break; 67810671Speter default: 679*18346Smckusick label = getlab(); 68010671Speter sprintf( labelname , PREFIXFORMAT , LABELPREFIX , label ); 68110671Speter putprintf( " .data" , 0 ); 68210671Speter aligndot(A_STRUCT); 68310671Speter putprintf( " .lcomm %s,%d" , 0 , 684*18346Smckusick labelname , lwidth( fvar -> type ) ); 68510671Speter putprintf( " .text" , 0 ); 686*18346Smckusick putleaf( P2NAME , 0 , 0 , fvartype , labelname ); 68710671Speter putLV( fvar -> symbol , ( fvar -> nl_block ) & 037 , 68810671Speter fvar -> value[ NL_OFFS ] , 68910671Speter fvar -> extra_flags , 690*18346Smckusick fvartype ); 691*18346Smckusick putstrop( P2STASG , ADDTYPE(fvartype, P2PTR) , 692*18346Smckusick lwidth( fvar -> type ) , 69310671Speter align( fvar -> type ) ); 69410671Speter putdot( filename , line ); 695*18346Smckusick putleaf( P2ICON , 0 , 0 , ADDTYPE(fvartype, P2PTR), labelname ); 696*18346Smckusick putop( P2FORCE , ADDTYPE(fvartype, P2PTR) ); 69710671Speter break; 69810671Speter } 69910671Speter putdot( filename , line ); 70010671Speter } 70110671Speter /* 70210671Speter * if there are nested procedures we must save the display. 70310671Speter */ 70410671Speter if ( parts[ cbn ] & NONLOCALVAR ) { 70510671Speter /* 70610671Speter * restore old display entry from save area 70710671Speter */ 70810671Speter putprintf( " movq %d(%s),%s+%d" , 0 709*18346Smckusick , DSAVEOFFSET , P2FPNAME 710*18346Smckusick , DISPLAYNAME , cbn * sizeof(struct dispsave) ); 71110671Speter } 71210671Speter } 71310671Speter 71410671Speter fp_epilogue(eecookiep) 71510671Speter struct entry_exit_cookie *eecookiep; 71610671Speter { 717*18346Smckusick stabline(line); 71810671Speter putprintf(" ret" , 0 ); 71910671Speter /* 72010671Speter * set the register save mask. 72110671Speter */ 72210671Speter putprintf(" .set %s%d,0x%x", 0, 723*18346Smckusick SAVE_MASK_LABEL, eecookiep -> savlabel, savmask()); 72410671Speter } 72510671Speter 72610671Speter fp_formalentry(eecookiep) 72710671Speter struct entry_exit_cookie *eecookiep; 72810671Speter { 72910671Speter 73011857Speter putprintf(" .align 1", 0); 731*18346Smckusick putprintf("%s%s:" , 0 , FORMALPREFIX , eecookiep -> extname ); 732*18346Smckusick putprintf(" .word %s%d", 0, SAVE_MASK_LABEL, eecookiep -> savlabel ); 73310671Speter putleaf( P2ICON , 0 , 0 , ADDTYPE( P2FTN | P2INT , P2PTR ) , "_FCALL" ); 734*18346Smckusick putRV( 0 , cbn , 73510671Speter eecookiep -> nlp -> value[ NL_OFFS ] + sizeof( struct formalrtn * ) , 73610671Speter NPARAM , P2PTR | P2STRTY ); 737*18346Smckusick putRV(0, cbn, eecookiep -> nlp -> value[NL_OFFS], NPARAM, P2PTR|P2STRTY); 73810671Speter putop( P2LISTOP , P2INT ); 73910671Speter putop( P2CALL , P2INT ); 74010671Speter putdot( filename , line ); 741*18346Smckusick putjbr( eecookiep -> toplabel ); 74210671Speter } 74310671Speter #endif vax 74410671Speter 74510671Speter #ifdef mc68000 74610671Speter 74710671Speter codeformain() 74810671Speter { 74910671Speter putprintf(" .text", 0); 75010671Speter putprintf(" .globl _main", 0); 75110671Speter putprintf("_main:", 0); 75210671Speter putprintf(" link %s,#0", 0, P2FPNAME); 75310671Speter if (opt('t')) { 75410671Speter putprintf(" pea 1", 0); 75510671Speter } else { 75610671Speter putprintf(" pea 0", 0); 75710671Speter } 75810671Speter putprintf(" jbsr _PCSTART", 0); 75910671Speter putprintf(" addql #4,sp", 0); 76010671Speter putprintf(" movl %s@(8),__argc", 0, P2FPNAME); 76110671Speter putprintf(" movl %s@(12),__argv", 0, P2FPNAME); 76210671Speter putprintf(" jbsr _program", 0); 76310671Speter putprintf(" pea 0", 0); 76410671Speter putprintf(" jbsr _PCEXIT", 0); 76510671Speter } 76610671Speter 76710671Speter prog_prologue(eecookiep) 76810671Speter struct entry_exit_cookie *eecookiep; 76910671Speter { 77010671Speter int ftnno = eecookiep -> nlp -> value[NL_ENTLOC]; 77110671Speter 77210671Speter putprintf(" .text", 0); 77310671Speter putprintf(" .globl _program", 0); 77410671Speter putprintf("_program:", 0); 77510671Speter putprintf(" link %s,#0", 0, P2FPNAME); 77610671Speter putprintf(" addl #-%s%d,sp", 0, FRAME_SIZE_LABEL, ftnno); 77710671Speter /* touch new end of stack, to break more stack space */ 77810671Speter putprintf(" tstb sp@(-%s%d)", 0, PAGE_BREAK_LABEL, ftnno); 77910671Speter putprintf(" moveml #%s%d,sp@", 0, SAVE_MASK_LABEL, ftnno); 78010671Speter } 78110671Speter 78210671Speter fp_prologue(eecookiep) 78310671Speter struct entry_exit_cookie *eecookiep; 78410671Speter { 78510671Speter int ftnno = eecookiep -> nlp -> value[NL_ENTLOC]; 78610671Speter 78710671Speter sextname(eecookiep -> extname, eecookiep -> nlp -> symbol, cbn - 1); 78810671Speter putprintf(" .text", 0); 78910671Speter putprintf(" .globl %s%s", 0, FORMALPREFIX, eecookiep -> extname); 79010671Speter putprintf(" .globl %s", 0, eecookiep -> extname); 79110671Speter putprintf("%s:", 0, eecookiep -> extname); 79210671Speter putprintf(" link %s,#0", 0, P2FPNAME); 79310671Speter putprintf(" addl #-%s%d,sp", 0, FRAME_SIZE_LABEL, ftnno); 79410671Speter /* touch new end of stack, to break more stack space */ 79510671Speter putprintf(" tstb sp@(-%s%d)", 0, PAGE_BREAK_LABEL, ftnno); 79610671Speter putprintf(" moveml #%s%d,sp@", 0, SAVE_MASK_LABEL, ftnno); 79710671Speter } 79810671Speter 79910671Speter fp_entrycode(eecookiep) 80010671Speter struct entry_exit_cookie *eecookiep; 80110671Speter { 802*18346Smckusick int proflabel = getlab(); 803*18346Smckusick int setjmp0 = getlab(); 80410671Speter 80510671Speter /* 80610671Speter * fill in the label cookie 80710671Speter */ 80810671Speter eecookiep -> toplabel = getlab(); 809*18346Smckusick putlab(eecookiep -> toplabel); 81010671Speter /* 81110671Speter * call mcount if we are profiling. 81210671Speter */ 81310671Speter if ( profflag ) { 81410671Speter putprintf(" movl #%s%d,a0", 0, LABELPREFIX, proflabel); 81510671Speter putprintf(" jsr mcount", 0); 81610671Speter putprintf(" .data", 0); 81710671Speter putprintf(" .even", 0); 818*18346Smckusick putlab(proflabel); 81910671Speter putprintf(" .long 0", 0); 82010671Speter putprintf(" .text", 0); 82110671Speter } 82210671Speter /* 82310671Speter * if there are nested procedures that access our variables 82410671Speter * we must save the display 82510671Speter */ 82610671Speter if (parts[cbn] & NONLOCALVAR) { 82710671Speter /* 82810671Speter * save the old display 82910671Speter */ 83010671Speter putprintf(" movl %s+%d,%s@(%d)", 0, 83110671Speter DISPLAYNAME, cbn * sizeof(struct dispsave), 83210671Speter P2FPNAME, DSAVEOFFSET); 83310671Speter /* 83410671Speter * set up the new display by saving the framepointer 83510671Speter * in the display structure. 83610671Speter */ 83710671Speter putprintf(" movl %s,%s+%d", 0, 83810671Speter P2FPNAME, DISPLAYNAME, cbn * sizeof(struct dispsave)); 83910671Speter } 84010671Speter /* 84110671Speter * zero local variables if checking is on 84210671Speter * by calling blkclr( bytes of locals , starting local address ); 84310671Speter */ 84410671Speter if ( opt( 't' ) && ( -sizes[ cbn ].om_max ) > DPOFF1 ) { 84510671Speter putleaf( P2ICON , 0 , 0 , ADDTYPE( P2FTN | P2INT , P2PTR ) 84610671Speter , "_blkclr" ); 84710671Speter putLV( 0 , cbn , sizes[ cbn ].om_max , NLOCAL , P2CHAR ); 84810671Speter putleaf( P2ICON , ( -sizes[ cbn ].om_max ) - DPOFF1 84910671Speter , 0 , P2INT , 0 ); 85010671Speter putop( P2LISTOP , P2INT ); 85110671Speter putop( P2CALL , P2INT ); 85210671Speter putdot( filename , line ); 85310671Speter } 85410671Speter /* 85510671Speter * set up goto vector if non-local goto to this frame 85610671Speter */ 85710671Speter if ( parts[ cbn ] & NONLOCALGOTO ) { 85810671Speter putleaf( P2ICON , 0 , 0 , ADDTYPE( P2FTN | P2INT , P2PTR ) 85910671Speter , "_setjmp" ); 86010671Speter putLV( 0 , cbn , GOTOENVOFFSET , NLOCAL , P2PTR|P2STRTY ); 86110671Speter putop( P2CALL , P2INT ); 86210671Speter putleaf( P2ICON , 0 , 0 , P2INT , 0 ); 86310671Speter putop( P2NE , P2INT ); 86410671Speter putleaf( P2ICON , setjmp0 , 0 , P2INT , 0 ); 86510671Speter putop( P2CBRANCH , P2INT ); 86610671Speter putdot( filename , line ); 86710671Speter /* 86810671Speter * on non-local goto, setjmp returns with address to 86910671Speter * be branched to. 87010671Speter */ 87110671Speter putprintf(" movl d0,a0", 0); 87210671Speter putprintf(" jmp a0@", 0); 873*18346Smckusick putlab(setjmp0); 87410671Speter } 87510671Speter } 87610671Speter 87710671Speter fp_exitcode(eecookiep) 87810671Speter struct entry_exit_cookie *eecookiep; 87910671Speter { 88010671Speter /* 88110671Speter * if there were file variables declared at this level 88210671Speter * call PCLOSE( ap ) to clean them up. 88310671Speter */ 88410671Speter if ( dfiles[ cbn ] ) { 88510671Speter putleaf( P2ICON , 0 , 0 , ADDTYPE( P2FTN | P2INT , P2PTR ) 88610671Speter , "_PCLOSE" ); 88710671Speter putleaf( P2REG , 0 , P2AP , ADDTYPE( P2CHAR , P2PTR ) , 0 ); 88810671Speter putop( P2CALL , P2INT ); 88910671Speter putdot( filename , line ); 89010671Speter } 89110671Speter /* 89210671Speter * if this is a function, 89310671Speter * the function variable is the return value. 89410671Speter * if it's a scalar valued function, return scalar, 89510671Speter * else, return a pointer to the structure value. 89610671Speter */ 89710671Speter if ( eecookiep -> nlp -> class == FUNC ) { 89810671Speter struct nl *fvar = eecookiep -> nlp -> ptr[ NL_FVAR ]; 89910671Speter long fvartype = p2type( fvar -> type ); 900*18346Smckusick long label; 90110671Speter char labelname[ BUFSIZ ]; 90210671Speter 90310671Speter switch ( classify( fvar -> type ) ) { 90410671Speter case TBOOL: 90510671Speter case TCHAR: 90610671Speter case TINT: 90710671Speter case TSCAL: 90810671Speter case TDOUBLE: 90910671Speter case TPTR: 91010671Speter putRV( fvar -> symbol , ( fvar -> nl_block ) & 037 , 91110671Speter fvar -> value[ NL_OFFS ] , 91210671Speter fvar -> extra_flags , 91310671Speter fvartype ); 91411857Speter putop( P2FORCE , fvartype ); 91510671Speter break; 91610671Speter default: 91710671Speter label = getlab(); 91810671Speter sprintf( labelname , PREFIXFORMAT , LABELPREFIX , label ); 91910671Speter putprintf(" .lcomm %s,%d", 0, 92010671Speter labelname, lwidth(fvar -> type)); 92110671Speter putleaf( P2NAME , 0 , 0 , fvartype , labelname ); 92210671Speter putLV( fvar -> symbol , ( fvar -> nl_block ) & 037 , 92310671Speter fvar -> value[ NL_OFFS ] , 92410671Speter fvar -> extra_flags , 92510671Speter fvartype ); 92611857Speter putstrop( P2STASG , ADDTYPE(fvartype, P2PTR) , 92711857Speter lwidth( fvar -> type ) , 92810671Speter align( fvar -> type ) ); 92910671Speter putdot( filename , line ); 93011857Speter putleaf( P2ICON , 0 , 0 , ADDTYPE(fvartype, P2PTR), labelname ); 93111857Speter putop( P2FORCE , ADDTYPE(fvartype, P2PTR) ); 93210671Speter break; 93310671Speter } 93410671Speter putdot( filename , line ); 93510671Speter } 93610671Speter /* 93710671Speter * if we saved a display, we must restore it. 93810671Speter */ 93910671Speter if ( parts[ cbn ] & NONLOCALVAR ) { 94010671Speter /* 94110671Speter * restore old display entry from save area 94210671Speter */ 94310671Speter putprintf(" movl %s@(%d),%s+%d", 0, 94410671Speter P2FPNAME, DSAVEOFFSET, 94510671Speter DISPLAYNAME, cbn * sizeof(struct dispsave)); 94610671Speter } 94710671Speter } 94810671Speter 94910671Speter fp_epilogue(eecookiep) 95010671Speter struct entry_exit_cookie *eecookiep; 95110671Speter { 95210671Speter /* 95310671Speter * all done by the second pass. 95410671Speter */ 95510671Speter } 95610671Speter 95710671Speter fp_formalentry(eecookiep) 95810671Speter struct entry_exit_cookie *eecookiep; 95910671Speter { 96010671Speter putprintf( "%s%s:" , 0 , FORMALPREFIX , eecookiep -> extname ); 96110671Speter putprintf(" link %s,#0", 0, P2FPNAME); 96210671Speter putprintf(" addl #-%s%d,sp", 0, FRAME_SIZE_LABEL, ftnno); 96310671Speter /* touch new end of stack, to break more stack space */ 96410671Speter putprintf(" tstb sp@(-%s%d)", 0, PAGE_BREAK_LABEL, ftnno); 96510671Speter putprintf(" moveml #%s%d,sp@", 0, SAVE_MASK_LABEL, ftnno); 96610671Speter putleaf( P2ICON , 0 , 0 , ADDTYPE( P2FTN | P2INT , P2PTR ) , "_FCALL" ); 96710671Speter putRV( 0 , cbn , 96810671Speter eecookiep -> nlp -> value[ NL_OFFS ] + sizeof( struct formalrtn * ) , 96910671Speter NPARAM , P2PTR | P2STRTY ); 97010671Speter putRV(0, cbn, eecookiep -> nlp -> value[NL_OFFS], NPARAM, P2PTR|P2STRTY); 97110671Speter putop( P2LISTOP , P2INT ); 97210671Speter putop( P2CALL , P2INT ); 97310671Speter putdot( filename , line ); 97410671Speter putjbr( eecookiep -> toplabel ); 97510671Speter } 97610671Speter #endif mc68000 9773363Speter #endif PC 978*18346Smckusick 979