1348a2a57Smckusick /* Copyright (c) 1979 Regents of the University of California */ 2348a2a57Smckusick 3*5b396f44Speter static char sccsid[] = "@(#)fend.c 1.4 03/24/81"; 4348a2a57Smckusick 5348a2a57Smckusick #include "whoami.h" 6348a2a57Smckusick #include "0.h" 7348a2a57Smckusick #include "tree.h" 8348a2a57Smckusick #include "opcode.h" 9348a2a57Smckusick #include "objfmt.h" 10348a2a57Smckusick #include "align.h" 11348a2a57Smckusick 12348a2a57Smckusick /* 13348a2a57Smckusick * this array keeps the pxp counters associated with 14348a2a57Smckusick * functions and procedures, so that they can be output 15348a2a57Smckusick * when their bodies are encountered 16348a2a57Smckusick */ 17348a2a57Smckusick int bodycnts[ DSPLYSZ ]; 18348a2a57Smckusick 19348a2a57Smckusick #ifdef PC 20348a2a57Smckusick # include "pc.h" 21348a2a57Smckusick # include "pcops.h" 22348a2a57Smckusick #endif PC 23348a2a57Smckusick 24348a2a57Smckusick #ifdef OBJ 25348a2a57Smckusick int cntpatch; 26348a2a57Smckusick int nfppatch; 27348a2a57Smckusick #endif OBJ 28348a2a57Smckusick 29348a2a57Smckusick struct nl *Fp; 30348a2a57Smckusick int pnumcnt; 31348a2a57Smckusick /* 32348a2a57Smckusick * Funcend is called to 33348a2a57Smckusick * finish a block by generating 34348a2a57Smckusick * the code for the statements. 35348a2a57Smckusick * It then looks for unresolved declarations 36348a2a57Smckusick * of labels, procedures and functions, 37348a2a57Smckusick * and cleans up the name list. 38348a2a57Smckusick * For the program, it checks the 39348a2a57Smckusick * semantics of the program 40348a2a57Smckusick * statement (yuchh). 41348a2a57Smckusick */ 42348a2a57Smckusick funcend(fp, bundle, endline) 43348a2a57Smckusick struct nl *fp; 44348a2a57Smckusick int *bundle; 45348a2a57Smckusick int endline; 46348a2a57Smckusick { 47348a2a57Smckusick register struct nl *p; 48348a2a57Smckusick register int i, b; 49348a2a57Smckusick int var, inp, out, *blk; 50348a2a57Smckusick bool chkref; 51348a2a57Smckusick struct nl *iop; 52348a2a57Smckusick char *cp; 53348a2a57Smckusick extern int cntstat; 54348a2a57Smckusick # ifdef PC 55f617c19fSmckusic int savlabel = getlab(); 56348a2a57Smckusick int toplabel = getlab(); 57348a2a57Smckusick int botlabel = getlab(); 58*5b396f44Speter char extname[ BUFSIZ ]; 59348a2a57Smckusick # endif PC 60348a2a57Smckusick 61348a2a57Smckusick cntstat = 0; 62348a2a57Smckusick /* 63348a2a57Smckusick * yyoutline(); 64348a2a57Smckusick */ 65348a2a57Smckusick if (program != NIL) 66348a2a57Smckusick line = program->value[3]; 67348a2a57Smckusick blk = bundle[2]; 68348a2a57Smckusick if (fp == NIL) { 69348a2a57Smckusick cbn--; 70348a2a57Smckusick # ifdef PTREE 71348a2a57Smckusick nesting--; 72348a2a57Smckusick # endif PTREE 73348a2a57Smckusick return; 74348a2a57Smckusick } 75348a2a57Smckusick #ifdef OBJ 76348a2a57Smckusick /* 77348a2a57Smckusick * Patch the branch to the 78348a2a57Smckusick * entry point of the function 79348a2a57Smckusick */ 80348a2a57Smckusick patch4(fp->entloc); 81348a2a57Smckusick /* 82348a2a57Smckusick * Put out the block entrance code and the block name. 83348a2a57Smckusick * HDRSZE is the number of bytes of info in the static 84348a2a57Smckusick * BEG data area exclusive of the proc name. It is 85348a2a57Smckusick * currently defined as: 86348a2a57Smckusick /* struct hdr { 87348a2a57Smckusick /* long framesze; /* number of bytes of local vars */ 88348a2a57Smckusick /* long nargs; /* number of bytes of arguments */ 89348a2a57Smckusick /* bool tests; /* TRUE => perform runtime tests */ 90348a2a57Smckusick /* short offset; /* offset of procedure in source file */ 91348a2a57Smckusick /* char name[1]; /* name of active procedure */ 92348a2a57Smckusick /* }; 93348a2a57Smckusick */ 94348a2a57Smckusick # define HDRSZE (2 * sizeof(long) + sizeof(short) + sizeof(bool)) 95348a2a57Smckusick var = put(2, ((lenstr(fp->symbol,0) + HDRSZE) << 8) 96348a2a57Smckusick | (cbn == 1 && opt('p') == 0 ? O_NODUMP: O_BEG), (long)0); 97348a2a57Smckusick /* 98348a2a57Smckusick * output the number of bytes of arguments 99348a2a57Smckusick * this is only checked on formal calls. 100348a2a57Smckusick */ 101348a2a57Smckusick put(2, O_CASE4, cbn == 1 ? (long)0 : (long)(fp->value[NL_OFFS]-DPOFF2)); 102348a2a57Smckusick /* 103348a2a57Smckusick * Output the runtime test mode for the routine 104348a2a57Smckusick */ 105348a2a57Smckusick put(2, sizeof(bool) == 2 ? O_CASE2 : O_CASE4, opt('t') ? TRUE : FALSE); 106348a2a57Smckusick /* 107348a2a57Smckusick * Output line number and routine name 108348a2a57Smckusick */ 109348a2a57Smckusick put(2, O_CASE2, bundle[1]); 110348a2a57Smckusick putstr(fp->symbol, 0); 111348a2a57Smckusick #endif OBJ 112348a2a57Smckusick #ifdef PC 113348a2a57Smckusick /* 114348a2a57Smckusick * put out the procedure entry code 115348a2a57Smckusick */ 116348a2a57Smckusick if ( fp -> class == PROG ) { 117348a2a57Smckusick putprintf( " .text" , 0 ); 118348a2a57Smckusick putprintf( " .align 1" , 0 ); 119348a2a57Smckusick putprintf( " .globl _main" , 0 ); 120348a2a57Smckusick putprintf( "_main:" , 0 ); 121348a2a57Smckusick putprintf( " .word 0" , 0 ); 122348a2a57Smckusick putprintf( " calls $0,_PCSTART" , 0 ); 123348a2a57Smckusick putprintf( " movl 4(ap),__argc" , 0 ); 124348a2a57Smckusick putprintf( " movl 8(ap),__argv" , 0 ); 125348a2a57Smckusick putprintf( " calls $0,_program" , 0 ); 126348a2a57Smckusick putprintf( " calls $0,_PCEXIT" , 0 ); 127348a2a57Smckusick ftnno = fp -> entloc; 128348a2a57Smckusick putprintf( " .text" , 0 ); 129348a2a57Smckusick putprintf( " .align 1" , 0 ); 130348a2a57Smckusick putprintf( " .globl _program" , 0 ); 131348a2a57Smckusick putprintf( "_program:" , 0 ); 132348a2a57Smckusick stabfunc( "program" , fp -> class , bundle[1] , 0 ); 133348a2a57Smckusick } else { 134348a2a57Smckusick ftnno = fp -> entloc; 135348a2a57Smckusick putprintf( " .text" , 0 ); 136348a2a57Smckusick putprintf( " .align 1" , 0 ); 137*5b396f44Speter sextname( extname , fp -> symbol , cbn ); 138*5b396f44Speter putprintf( " .globl %s" , 0 , extname ); 139*5b396f44Speter putprintf( "%s:" , 0 , extname ); 140348a2a57Smckusick stabfunc( fp -> symbol , fp -> class , bundle[1] , cbn - 1 ); 141348a2a57Smckusick for ( p = fp -> chain ; p != NIL ; p = p -> chain ) { 142348a2a57Smckusick stabparam( p -> symbol , p2type( p -> type ) 143348a2a57Smckusick , p -> value[ NL_OFFS ] , lwidth( p -> type ) ); 144348a2a57Smckusick } 145348a2a57Smckusick if ( fp -> class == FUNC ) { 146348a2a57Smckusick /* 147348a2a57Smckusick * stab the function variable 148348a2a57Smckusick */ 149348a2a57Smckusick p = fp -> ptr[ NL_FVAR ]; 150348a2a57Smckusick stablvar( p -> symbol , p2type( p -> type ) , cbn 151348a2a57Smckusick , p -> value[ NL_OFFS ] , lwidth( p -> type ) ); 152348a2a57Smckusick } 153348a2a57Smckusick /* 154348a2a57Smckusick * stab local variables 155348a2a57Smckusick * rummage down hash chain links. 156348a2a57Smckusick */ 157348a2a57Smckusick for ( i = 0 ; i <= 077 ; i++ ) { 158348a2a57Smckusick for ( p = disptab[ i ] ; p != NIL ; p = p->nl_next) { 159348a2a57Smckusick if ( ( p -> nl_block & 037 ) != cbn ) { 160348a2a57Smckusick break; 161348a2a57Smckusick } 162348a2a57Smckusick /* 163348a2a57Smckusick * stab local variables 164348a2a57Smckusick * that's named variables, but not params 165348a2a57Smckusick */ 166348a2a57Smckusick if ( ( p -> symbol != NIL ) 167348a2a57Smckusick && ( p -> class == VAR ) 168348a2a57Smckusick && ( p -> value[ NL_OFFS ] < 0 ) ) { 169348a2a57Smckusick stablvar( p -> symbol , p2type( p -> type ) , cbn 170348a2a57Smckusick , p -> value[ NL_OFFS ] , lwidth( p -> type ) ); 171348a2a57Smckusick } 172348a2a57Smckusick } 173348a2a57Smckusick } 174348a2a57Smckusick } 175348a2a57Smckusick stablbrac( cbn ); 176348a2a57Smckusick /* 177348a2a57Smckusick * register save mask 178348a2a57Smckusick */ 179f617c19fSmckusic putprintf( " .word " , 1 ); 180f617c19fSmckusic putprintf( PREFIXFORMAT , 0 , LABELPREFIX , savlabel ); 181348a2a57Smckusick putjbr( botlabel ); 182348a2a57Smckusick putlab( toplabel ); 183348a2a57Smckusick if ( profflag ) { 184348a2a57Smckusick /* 185348a2a57Smckusick * call mcount for profiling 186348a2a57Smckusick */ 187348a2a57Smckusick putprintf( " moval 1f,r0" , 0 ); 188348a2a57Smckusick putprintf( " jsb mcount" , 0 ); 189348a2a57Smckusick putprintf( " .data" , 0 ); 190348a2a57Smckusick putprintf( " .align 2" , 0 ); 191348a2a57Smckusick putprintf( "1:" , 0 ); 192348a2a57Smckusick putprintf( " .long 0" , 0 ); 193348a2a57Smckusick putprintf( " .text" , 0 ); 194348a2a57Smckusick } 195348a2a57Smckusick /* 196348a2a57Smckusick * set up unwind exception vector. 197348a2a57Smckusick */ 198348a2a57Smckusick putprintf( " moval %s,%d(%s)" , 0 199348a2a57Smckusick , UNWINDNAME , UNWINDOFFSET , P2FPNAME ); 200348a2a57Smckusick /* 201348a2a57Smckusick * save address of display entry, for unwind. 202348a2a57Smckusick */ 203348a2a57Smckusick putprintf( " moval %s+%d,%d(%s)" , 0 204348a2a57Smckusick , DISPLAYNAME , cbn * sizeof(struct dispsave) 205348a2a57Smckusick , DPTROFFSET , P2FPNAME ); 206348a2a57Smckusick /* 207348a2a57Smckusick * save old display 208348a2a57Smckusick */ 209348a2a57Smckusick putprintf( " movq %s+%d,%d(%s)" , 0 210348a2a57Smckusick , DISPLAYNAME , cbn * sizeof(struct dispsave) 211348a2a57Smckusick , DSAVEOFFSET , P2FPNAME ); 212348a2a57Smckusick /* 213348a2a57Smckusick * set up new display by saving AP and FP in appropriate 214348a2a57Smckusick * slot in display structure. 215348a2a57Smckusick */ 216348a2a57Smckusick putprintf( " movq %s,%s+%d" , 0 217348a2a57Smckusick , P2APNAME , DISPLAYNAME , cbn * sizeof(struct dispsave) ); 218348a2a57Smckusick /* 219348a2a57Smckusick * ask second pass to allocate known locals 220348a2a57Smckusick */ 221348a2a57Smckusick putlbracket( ftnno , -sizes[ cbn ].om_max ); 222348a2a57Smckusick /* 223348a2a57Smckusick * and zero them if checking is on 224348a2a57Smckusick * by calling blkclr( bytes of locals , starting local address ); 225348a2a57Smckusick */ 226403dbb08Smckusic if ( opt( 't' ) && ( -sizes[ cbn ].om_max ) > DPOFF1 ) { 227348a2a57Smckusick putleaf( P2ICON , 0 , 0 , ADDTYPE( P2FTN | P2INT , P2PTR ) 228348a2a57Smckusick , "_blkclr" ); 229348a2a57Smckusick putleaf( P2ICON , ( -sizes[ cbn ].om_max ) - DPOFF1 230348a2a57Smckusick , 0 , P2INT , 0 ); 231348a2a57Smckusick putLV( 0 , cbn , sizes[ cbn ].om_max , P2CHAR ); 232348a2a57Smckusick putop( P2LISTOP , P2INT ); 233348a2a57Smckusick putop( P2CALL , P2INT ); 234348a2a57Smckusick putdot( filename , line ); 235348a2a57Smckusick } 236348a2a57Smckusick #endif PC 237348a2a57Smckusick if ( monflg ) { 238348a2a57Smckusick if ( fp -> value[ NL_CNTR ] != 0 ) { 239348a2a57Smckusick inccnt( fp -> value [ NL_CNTR ] ); 240348a2a57Smckusick } 241348a2a57Smckusick inccnt( bodycnts[ fp -> nl_block & 037 ] ); 242348a2a57Smckusick } 243348a2a57Smckusick if (fp->class == PROG) { 244348a2a57Smckusick /* 245348a2a57Smckusick * The glorious buffers option. 246348a2a57Smckusick * 0 = don't buffer output 247348a2a57Smckusick * 1 = line buffer output 248348a2a57Smckusick * 2 = 512 byte buffer output 249348a2a57Smckusick */ 250348a2a57Smckusick # ifdef OBJ 251348a2a57Smckusick if (opt('b') != 1) 252348a2a57Smckusick put(1, O_BUFF | opt('b') << 8); 253348a2a57Smckusick # endif OBJ 254348a2a57Smckusick # ifdef PC 255348a2a57Smckusick if ( opt( 'b' ) != 1 ) { 256348a2a57Smckusick putleaf( P2ICON , 0 , 0 257348a2a57Smckusick , ADDTYPE( P2FTN | P2INT , P2PTR ) , "_BUFF" ); 258348a2a57Smckusick putleaf( P2ICON , opt( 'b' ) , 0 , P2INT , 0 ); 259348a2a57Smckusick putop( P2CALL , P2INT ); 260348a2a57Smckusick putdot( filename , line ); 261348a2a57Smckusick } 262348a2a57Smckusick # endif PC 263348a2a57Smckusick out = 0; 264348a2a57Smckusick for (p = fp->chain; p != NIL; p = p->chain) { 265348a2a57Smckusick if (strcmp(p->symbol, "input") == 0) { 266348a2a57Smckusick inp++; 267348a2a57Smckusick continue; 268348a2a57Smckusick } 269348a2a57Smckusick if (strcmp(p->symbol, "output") == 0) { 270348a2a57Smckusick out++; 271348a2a57Smckusick continue; 272348a2a57Smckusick } 273348a2a57Smckusick iop = lookup1(p->symbol); 274348a2a57Smckusick if (iop == NIL || bn != cbn) { 275348a2a57Smckusick error("File %s listed in program statement but not declared", p->symbol); 276348a2a57Smckusick continue; 277348a2a57Smckusick } 278348a2a57Smckusick if (iop->class != VAR) { 279348a2a57Smckusick error("File %s listed in program statement but declared as a %s", p->symbol, classes[iop->class]); 280348a2a57Smckusick continue; 281348a2a57Smckusick } 282348a2a57Smckusick if (iop->type == NIL) 283348a2a57Smckusick continue; 284348a2a57Smckusick if (iop->type->class != FILET) { 285348a2a57Smckusick error("File %s listed in program statement but defined as %s", 286348a2a57Smckusick p->symbol, nameof(iop->type)); 287348a2a57Smckusick continue; 288348a2a57Smckusick } 289348a2a57Smckusick # ifdef OBJ 290348a2a57Smckusick put(2, O_CON24, text(iop->type) ? 0 : width(iop->type->type)); 291348a2a57Smckusick i = lenstr(p->symbol,0); 292348a2a57Smckusick put(2, O_CON24, i); 293348a2a57Smckusick put(2, O_LVCON, i); 294348a2a57Smckusick putstr(p->symbol, 0); 295348a2a57Smckusick put(2, O_LV | bn<<8+INDX, (int)iop->value[NL_OFFS]); 296348a2a57Smckusick put(1, O_DEFNAME); 297348a2a57Smckusick # endif OBJ 298348a2a57Smckusick # ifdef PC 299348a2a57Smckusick putleaf( P2ICON , 0 , 0 300348a2a57Smckusick , ADDTYPE( P2FTN | P2INT , P2PTR ) 301348a2a57Smckusick , "_DEFNAME" ); 302348a2a57Smckusick putLV( p -> symbol , bn , iop -> value[NL_OFFS] 303348a2a57Smckusick , p2type( iop ) ); 304348a2a57Smckusick putCONG( p -> symbol , strlen( p -> symbol ) 305348a2a57Smckusick , LREQ ); 306348a2a57Smckusick putop( P2LISTOP , P2INT ); 307348a2a57Smckusick putleaf( P2ICON , strlen( p -> symbol ) 308348a2a57Smckusick , 0 , P2INT , 0 ); 309348a2a57Smckusick putop( P2LISTOP , P2INT ); 310348a2a57Smckusick putleaf( P2ICON 311348a2a57Smckusick , text(iop->type) ? 0 : width(iop->type->type) 312348a2a57Smckusick , 0 , P2INT , 0 ); 313348a2a57Smckusick putop( P2LISTOP , P2INT ); 314348a2a57Smckusick putop( P2CALL , P2INT ); 315348a2a57Smckusick putdot( filename , line ); 316348a2a57Smckusick # endif PC 317348a2a57Smckusick } 318348a2a57Smckusick if (out == 0 && fp->chain != NIL) { 319348a2a57Smckusick recovered(); 320348a2a57Smckusick error("The file output must appear in the program statement file list"); 321348a2a57Smckusick } 322348a2a57Smckusick } 323348a2a57Smckusick /* 324348a2a57Smckusick * Process the prog/proc/func body 325348a2a57Smckusick */ 326348a2a57Smckusick noreach = 0; 327348a2a57Smckusick line = bundle[1]; 328348a2a57Smckusick statlist(blk); 329348a2a57Smckusick # ifdef PTREE 330348a2a57Smckusick { 331348a2a57Smckusick pPointer Body = tCopy( blk ); 332348a2a57Smckusick 333348a2a57Smckusick pDEF( PorFHeader[ nesting -- ] ).PorFBody = Body; 334348a2a57Smckusick } 335348a2a57Smckusick # endif PTREE 336348a2a57Smckusick # ifdef OBJ 337348a2a57Smckusick if (cbn== 1 && monflg != 0) { 338348a2a57Smckusick patchfil(cntpatch - 2, (long)cnts, 2); 339348a2a57Smckusick patchfil(nfppatch - 2, (long)pfcnt, 2); 340348a2a57Smckusick } 341348a2a57Smckusick # endif OBJ 342348a2a57Smckusick # ifdef PC 343348a2a57Smckusick if ( fp -> class == PROG && monflg ) { 344348a2a57Smckusick putleaf( P2ICON , 0 , 0 , ADDTYPE( P2FTN | P2INT , P2PTR ) 345348a2a57Smckusick , "_PMFLUSH" ); 346348a2a57Smckusick putleaf( P2ICON , cnts , 0 , P2INT , 0 ); 347348a2a57Smckusick putleaf( P2ICON , pfcnt , 0 , P2INT , 0 ); 348348a2a57Smckusick putop( P2LISTOP , P2INT ); 349348a2a57Smckusick putLV( PCPCOUNT , 0 , 0 , P2INT ); 350348a2a57Smckusick putop( P2LISTOP , P2INT ); 351348a2a57Smckusick putop( P2CALL , P2INT ); 352348a2a57Smckusick putdot( filename , line ); 353348a2a57Smckusick } 354348a2a57Smckusick # endif PC 355348a2a57Smckusick if (fp->class == PROG && inp == 0 && (input->nl_flags & (NUSED|NMOD)) != 0) { 356348a2a57Smckusick recovered(); 357348a2a57Smckusick error("Input is used but not defined in the program statement"); 358348a2a57Smckusick } 359348a2a57Smckusick /* 360348a2a57Smckusick * Clean up the symbol table displays and check for unresolves 361348a2a57Smckusick */ 362348a2a57Smckusick line = endline; 363348a2a57Smckusick b = cbn; 364348a2a57Smckusick Fp = fp; 365348a2a57Smckusick chkref = syneflg == errcnt[cbn] && opt('w') == 0; 366348a2a57Smckusick for (i = 0; i <= 077; i++) { 367348a2a57Smckusick for (p = disptab[i]; p != NIL && (p->nl_block & 037) == b; p = p->nl_next) { 368348a2a57Smckusick /* 369348a2a57Smckusick * Check for variables defined 370348a2a57Smckusick * but not referenced 371348a2a57Smckusick */ 372348a2a57Smckusick if (chkref && p->symbol != NIL) 373348a2a57Smckusick switch (p->class) { 374348a2a57Smckusick case FIELD: 375348a2a57Smckusick /* 376348a2a57Smckusick * If the corresponding record is 377348a2a57Smckusick * unused, we shouldn't complain about 378348a2a57Smckusick * the fields. 379348a2a57Smckusick */ 380348a2a57Smckusick default: 381348a2a57Smckusick if ((p->nl_flags & (NUSED|NMOD)) == 0) { 382348a2a57Smckusick warning(); 383348a2a57Smckusick nerror("%s %s is neither used nor set", classes[p->class], p->symbol); 384348a2a57Smckusick break; 385348a2a57Smckusick } 386348a2a57Smckusick /* 387348a2a57Smckusick * If a var parameter is either 388348a2a57Smckusick * modified or used that is enough. 389348a2a57Smckusick */ 390348a2a57Smckusick if (p->class == REF) 391348a2a57Smckusick continue; 392348a2a57Smckusick # ifdef OBJ 393348a2a57Smckusick if ((p->nl_flags & NUSED) == 0) { 394348a2a57Smckusick warning(); 395348a2a57Smckusick nerror("%s %s is never used", classes[p->class], p->symbol); 396348a2a57Smckusick break; 397348a2a57Smckusick } 398348a2a57Smckusick # endif OBJ 399348a2a57Smckusick # ifdef PC 400348a2a57Smckusick if (((p->nl_flags & NUSED) == 0) && ((p->ext_flags & NEXTERN) == 0)) { 401348a2a57Smckusick warning(); 402348a2a57Smckusick nerror("%s %s is never used", classes[p->class], p->symbol); 403348a2a57Smckusick break; 404348a2a57Smckusick } 405348a2a57Smckusick # endif PC 406348a2a57Smckusick if ((p->nl_flags & NMOD) == 0) { 407348a2a57Smckusick warning(); 408348a2a57Smckusick nerror("%s %s is used but never set", classes[p->class], p->symbol); 409348a2a57Smckusick break; 410348a2a57Smckusick } 411348a2a57Smckusick case LABEL: 412348a2a57Smckusick case FVAR: 413348a2a57Smckusick case BADUSE: 414348a2a57Smckusick break; 415348a2a57Smckusick } 416348a2a57Smckusick switch (p->class) { 417348a2a57Smckusick case BADUSE: 418348a2a57Smckusick cp = "s"; 419348a2a57Smckusick if (p->chain->ud_next == NIL) 420348a2a57Smckusick cp++; 421348a2a57Smckusick eholdnl(); 422348a2a57Smckusick if (p->value[NL_KINDS] & ISUNDEF) 423348a2a57Smckusick nerror("%s undefined on line%s", p->symbol, cp); 424348a2a57Smckusick else 425348a2a57Smckusick nerror("%s improperly used on line%s", p->symbol, cp); 426348a2a57Smckusick pnumcnt = 10; 427348a2a57Smckusick pnums(p->chain); 428348a2a57Smckusick pchr('\n'); 429348a2a57Smckusick break; 430348a2a57Smckusick 431348a2a57Smckusick case FUNC: 432348a2a57Smckusick case PROC: 433348a2a57Smckusick # ifdef OBJ 434348a2a57Smckusick if ((p->nl_flags & NFORWD)) 435348a2a57Smckusick nerror("Unresolved forward declaration of %s %s", classes[p->class], p->symbol); 436348a2a57Smckusick # endif OBJ 437348a2a57Smckusick # ifdef PC 438348a2a57Smckusick if ((p->nl_flags & NFORWD) && ((p->ext_flags & NEXTERN) == 0)) 439348a2a57Smckusick nerror("Unresolved forward declaration of %s %s", classes[p->class], p->symbol); 440348a2a57Smckusick # endif PC 441348a2a57Smckusick break; 442348a2a57Smckusick 443348a2a57Smckusick case LABEL: 444348a2a57Smckusick if (p->nl_flags & NFORWD) 445348a2a57Smckusick nerror("label %s was declared but not defined", p->symbol); 446348a2a57Smckusick break; 447348a2a57Smckusick case FVAR: 448348a2a57Smckusick if ((p->nl_flags & NMOD) == 0) 449348a2a57Smckusick nerror("No assignment to the function variable"); 450348a2a57Smckusick break; 451348a2a57Smckusick } 452348a2a57Smckusick } 453348a2a57Smckusick /* 454348a2a57Smckusick * Pop this symbol 455348a2a57Smckusick * table slot 456348a2a57Smckusick */ 457348a2a57Smckusick disptab[i] = p; 458348a2a57Smckusick } 459348a2a57Smckusick 460348a2a57Smckusick # ifdef OBJ 461348a2a57Smckusick put(1, O_END); 462348a2a57Smckusick # endif OBJ 463348a2a57Smckusick # ifdef PC 464348a2a57Smckusick /* 465348a2a57Smckusick * if there were file variables declared at this level 466348a2a57Smckusick * call pclose( &__disply[ cbn ] ) to clean them up. 467348a2a57Smckusick */ 468348a2a57Smckusick if ( dfiles[ cbn ] ) { 469348a2a57Smckusick putleaf( P2ICON , 0 , 0 , ADDTYPE( P2FTN | P2INT , P2PTR ) 470348a2a57Smckusick , "_PCLOSE" ); 471348a2a57Smckusick putRV( DISPLAYNAME , 0 , cbn * sizeof( struct dispsave ) 472348a2a57Smckusick , P2PTR | P2CHAR ); 473348a2a57Smckusick putop( P2CALL , P2INT ); 474348a2a57Smckusick putdot( filename , line ); 475348a2a57Smckusick } 476348a2a57Smckusick /* 477348a2a57Smckusick * if this is a function, 478348a2a57Smckusick * the function variable is the return value. 479348a2a57Smckusick * if it's a scalar valued function, return scalar, 480348a2a57Smckusick * else, return a pointer to the structure value. 481348a2a57Smckusick */ 482348a2a57Smckusick if ( fp -> class == FUNC ) { 483348a2a57Smckusick struct nl *fvar = fp -> ptr[ NL_FVAR ]; 484348a2a57Smckusick long fvartype = p2type( fvar -> type ); 485348a2a57Smckusick long label; 486348a2a57Smckusick char labelname[ BUFSIZ ]; 487348a2a57Smckusick 488348a2a57Smckusick switch ( classify( fvar -> type ) ) { 489348a2a57Smckusick case TBOOL: 490348a2a57Smckusick case TCHAR: 491348a2a57Smckusick case TINT: 492348a2a57Smckusick case TSCAL: 493348a2a57Smckusick case TDOUBLE: 494348a2a57Smckusick case TPTR: 495348a2a57Smckusick putRV( fvar -> symbol , ( fvar -> nl_block ) & 037 496348a2a57Smckusick , fvar -> value[ NL_OFFS ] , fvartype ); 497348a2a57Smckusick break; 498348a2a57Smckusick default: 499348a2a57Smckusick label = getlab(); 500348a2a57Smckusick sprintf( labelname , PREFIXFORMAT , 501348a2a57Smckusick LABELPREFIX , label ); 502348a2a57Smckusick putprintf( " .data" , 0 ); 503348a2a57Smckusick putprintf( " .lcomm %s,%d" , 0 , 504348a2a57Smckusick labelname , lwidth( fvar -> type ) ); 505348a2a57Smckusick putprintf( " .text" , 0 ); 506348a2a57Smckusick putleaf( P2NAME , 0 , 0 , fvartype , labelname ); 507348a2a57Smckusick putLV( fvar -> symbol , ( fvar -> nl_block ) & 037 508348a2a57Smckusick , fvar -> value[ NL_OFFS ] , fvartype ); 509348a2a57Smckusick putstrop( P2STASG , fvartype , lwidth( fvar -> type ) , 510348a2a57Smckusick align( fvar -> type ) ); 511348a2a57Smckusick putdot( filename , line ); 512348a2a57Smckusick putleaf( P2ICON , 0 , 0 , fvartype , labelname ); 513348a2a57Smckusick break; 514348a2a57Smckusick } 515348a2a57Smckusick putop( P2FORCE , fvartype ); 516348a2a57Smckusick putdot( filename , line ); 517348a2a57Smckusick } 518348a2a57Smckusick /* 519348a2a57Smckusick * restore old display entry from save area 520348a2a57Smckusick */ 521348a2a57Smckusick 522348a2a57Smckusick putprintf( " movq %d(%s),%s+%d" , 0 523348a2a57Smckusick , DSAVEOFFSET , P2FPNAME 524348a2a57Smckusick , DISPLAYNAME , cbn * sizeof(struct dispsave) ); 525348a2a57Smckusick stabrbrac( cbn ); 526348a2a57Smckusick putprintf( " ret" , 0 ); 527348a2a57Smckusick /* 528348a2a57Smckusick * let the second pass allocate locals 529f617c19fSmckusic * and registers 530348a2a57Smckusick */ 531f617c19fSmckusic putprintf( " .set " , 1 ); 532f617c19fSmckusic putprintf( PREFIXFORMAT , 1 , LABELPREFIX , savlabel ); 533f617c19fSmckusic putprintf( ", 0x%x" , 0 , savmask() ); 534348a2a57Smckusick putlab( botlabel ); 535348a2a57Smckusick putprintf( " subl2 $LF%d,sp" , 0 , ftnno ); 536348a2a57Smckusick putrbracket( ftnno ); 537348a2a57Smckusick putjbr( toplabel ); 538348a2a57Smckusick /* 539348a2a57Smckusick * declare pcp counters, if any 540348a2a57Smckusick */ 541348a2a57Smckusick if ( monflg && fp -> class == PROG ) { 542348a2a57Smckusick putprintf( " .data" , 0 ); 543348a2a57Smckusick putprintf( " .comm " , 1 ); 544348a2a57Smckusick putprintf( PCPCOUNT , 1 ); 545348a2a57Smckusick putprintf( ",%d" , 0 , ( cnts + 1 ) * sizeof (long) ); 546348a2a57Smckusick putprintf( " .text" , 0 ); 547348a2a57Smckusick } 548348a2a57Smckusick # endif PC 549348a2a57Smckusick #ifdef DEBUG 550348a2a57Smckusick dumpnl(fp->ptr[2], fp->symbol); 551348a2a57Smckusick #endif 552348a2a57Smckusick /* 553348a2a57Smckusick * Restore the 554348a2a57Smckusick * (virtual) name list 555348a2a57Smckusick * position 556348a2a57Smckusick */ 557348a2a57Smckusick nlfree(fp->ptr[2]); 558348a2a57Smckusick /* 559348a2a57Smckusick * Proc/func has been 560348a2a57Smckusick * resolved 561348a2a57Smckusick */ 562348a2a57Smckusick fp->nl_flags &= ~NFORWD; 563348a2a57Smckusick /* 564348a2a57Smckusick * Patch the beg 565348a2a57Smckusick * of the proc/func to 566348a2a57Smckusick * the proper variable size 567348a2a57Smckusick */ 568348a2a57Smckusick if (Fp == NIL) 569348a2a57Smckusick elineon(); 570348a2a57Smckusick # ifdef OBJ 571348a2a57Smckusick patchfil(var, (long)(-sizes[cbn].om_max), 2); 572348a2a57Smckusick # endif OBJ 573348a2a57Smckusick cbn--; 574348a2a57Smckusick if (inpflist(fp->symbol)) { 575348a2a57Smckusick opop('l'); 576348a2a57Smckusick } 577348a2a57Smckusick } 578*5b396f44Speter 579*5b396f44Speter #ifdef PC 580*5b396f44Speter /* 581*5b396f44Speter * construct the long name of a function based on it's static nesting. 582*5b396f44Speter * into a caller-supplied buffer (that should be about BUFSIZ big). 583*5b396f44Speter */ 584*5b396f44Speter sextname( buffer , name , level ) 585*5b396f44Speter char buffer[]; 586*5b396f44Speter char *name; 587*5b396f44Speter int level; 588*5b396f44Speter { 589*5b396f44Speter char *starthere; 590*5b396f44Speter int i; 591*5b396f44Speter 592*5b396f44Speter starthere = &buffer[0]; 593*5b396f44Speter for ( i = 1 ; i < level ; i++ ) { 594*5b396f44Speter sprintf( starthere , EXTFORMAT , enclosing[ i ] ); 595*5b396f44Speter starthere += strlen( enclosing[ i ] ) + 1; 596*5b396f44Speter } 597*5b396f44Speter sprintf( starthere , EXTFORMAT , p -> symbol ); 598*5b396f44Speter starthere += strlen( p -> symbol ) + 1; 599*5b396f44Speter if ( starthere >= &buffer[ BUFSIZ ] ) { 600*5b396f44Speter panic( "sextname" ); 601*5b396f44Speter } 602*5b396f44Speter } 603*5b396f44Speter #endif PC 604