1 /*- 2 * Copyright (c) 1980, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * %sccs.include.redist.c% 6 */ 7 8 #ifndef lint 9 static char sccsid[] = "@(#)fend.c 8.1 (Berkeley) 06/06/93"; 10 #endif /* not lint */ 11 12 #include "whoami.h" 13 #include "0.h" 14 #include "tree.h" 15 #include "opcode.h" 16 #include "objfmt.h" 17 #include "align.h" 18 #include "tmps.h" 19 20 /* 21 * this array keeps the pxp counters associated with 22 * functions and procedures, so that they can be output 23 * when their bodies are encountered 24 */ 25 int bodycnts[ DSPLYSZ ]; 26 27 #ifdef PC 28 # include "pc.h" 29 # include <pcc.h> 30 #endif PC 31 32 #ifdef OBJ 33 int cntpatch; 34 int nfppatch; 35 #endif OBJ 36 37 #include "tree_ty.h" 38 39 struct nl *Fp; 40 int pnumcnt; 41 /* 42 * Funcend is called to 43 * finish a block by generating 44 * the code for the statements. 45 * It then looks for unresolved declarations 46 * of labels, procedures and functions, 47 * and cleans up the name list. 48 * For the program, it checks the 49 * semantics of the program 50 * statement (yuchh). 51 */ 52 funcend(fp, bundle, endline) 53 struct nl *fp; 54 struct tnode *bundle; 55 int endline; 56 { 57 register struct nl *p; 58 register int i, b; 59 int inp, out; 60 struct tnode *blk; 61 bool chkref; 62 struct nl *iop; 63 char *cp; 64 extern int cntstat; 65 # ifdef PC 66 struct entry_exit_cookie eecookie; 67 # endif PC 68 # ifndef PC 69 int var; 70 # endif PC 71 72 cntstat = 0; 73 /* 74 * yyoutline(); 75 */ 76 if (program != NIL) 77 line = program->value[3]; 78 blk = bundle->stmnt_blck.stmnt_list; 79 if (fp == NIL) { 80 cbn--; 81 # ifdef PTREE 82 nesting--; 83 # endif PTREE 84 return; 85 } 86 #ifdef OBJ 87 /* 88 * Patch the branch to the entry point of the function. 89 * Assure alignment of O_BEG structure. 90 */ 91 if (((int)lc & 02) == 0) 92 word(0); 93 patch4((PTR_DCL) fp->value[NL_ENTLOC]); 94 /* 95 * Put out the block entrance code and the block name. 96 * HDRSZE is the number of bytes of info in the static 97 * BEG data area exclusive of the proc name. It is 98 * currently defined as: 99 /* struct hdr { 100 /* long framesze; /* number of bytes of local vars */ 101 /* long nargs; /* number of bytes of arguments */ 102 /* bool tests; /* TRUE => perform runtime tests */ 103 /* short offset; /* offset of procedure in source file */ 104 /* char name[1]; /* name of active procedure */ 105 /* }; 106 */ 107 # define HDRSZE (2 * sizeof(long) + sizeof(short) + sizeof(bool)) 108 var = put(2, ((lenstr(fp->symbol,0) + HDRSZE) << 8) 109 | (cbn == 1 && opt('p') == 0 ? O_NODUMP: O_BEG), (long)0); 110 /* 111 * output the number of bytes of arguments 112 * this is only checked on formal calls. 113 */ 114 (void) put(2, O_CASE4, cbn == 1 ? (long)0 : (long)(fp->value[NL_OFFS]-DPOFF2)); 115 /* 116 * Output the runtime test mode for the routine 117 */ 118 (void) put(2, sizeof(bool) == 2 ? O_CASE2 : O_CASE4, opt('t') ? TRUE : FALSE); 119 /* 120 * Output line number and routine name 121 */ 122 (void) put(2, O_CASE2, bundle->stmnt_blck.line_no); 123 putstr(fp->symbol, 0); 124 #endif OBJ 125 #ifdef PC 126 /* 127 * put out the procedure entry code 128 */ 129 eecookie.nlp = fp; 130 if ( fp -> class == PROG ) { 131 /* 132 * If there is a label declaration in the main routine 133 * then there may be a non-local goto to it that does 134 * not appear in this module. We have to assume that 135 * such a reference may occur and generate code to 136 * prepare for it. 137 */ 138 if ( parts[ cbn ] & LPRT ) { 139 parts[ cbn ] |= ( NONLOCALVAR | NONLOCALGOTO ); 140 } 141 codeformain(); 142 ftnno = fp -> value[NL_ENTLOC]; 143 prog_prologue(&eecookie); 144 stabline(bundle->stmnt_blck.line_no); 145 stabfunc(fp, "program", bundle->stmnt_blck.line_no , (long) 0 ); 146 } else { 147 ftnno = fp -> value[NL_ENTLOC]; 148 fp_prologue(&eecookie); 149 stabline(bundle->stmnt_blck.line_no); 150 stabfunc(fp, fp->symbol, bundle->stmnt_blck.line_no, 151 (long)(cbn - 1)); 152 for ( p = fp -> chain ; p != NIL ; p = p -> chain ) { 153 stabparam( p , p -> value[ NL_OFFS ] , (int) lwidth(p->type)); 154 } 155 if ( fp -> class == FUNC ) { 156 /* 157 * stab the function variable 158 */ 159 p = fp -> ptr[ NL_FVAR ]; 160 stablvar( p , p -> value[ NL_OFFS ] , (int) lwidth( p -> type)); 161 } 162 /* 163 * stab local variables 164 * rummage down hash chain links. 165 */ 166 for ( i = 0 ; i <= 077 ; i++ ) { 167 for ( p = disptab[ i ] ; p != NIL ; p = p->nl_next) { 168 if ( ( p -> nl_block & 037 ) != cbn ) { 169 break; 170 } 171 /* 172 * stab locals (not parameters) 173 */ 174 if ( p -> symbol != NIL ) { 175 if ( p -> class == VAR && p -> value[ NL_OFFS ] < 0 ) { 176 stablvar( p , p -> value[ NL_OFFS ] , 177 (int) lwidth( p -> type ) ); 178 } else if ( p -> class == CONST ) { 179 stabconst( p ); 180 } 181 } 182 } 183 } 184 } 185 stablbrac( cbn ); 186 /* 187 * ask second pass to allocate known locals 188 */ 189 putlbracket(ftnno, &sizes[cbn]); 190 fp_entrycode(&eecookie); 191 #endif PC 192 if ( monflg ) { 193 if ( fp -> value[ NL_CNTR ] != 0 ) { 194 inccnt( fp -> value [ NL_CNTR ] ); 195 } 196 inccnt( bodycnts[ fp -> nl_block & 037 ] ); 197 } 198 if (fp->class == PROG) { 199 /* 200 * The glorious buffers option. 201 * 0 = don't buffer output 202 * 1 = line buffer output 203 * 2 = 512 byte buffer output 204 */ 205 # ifdef OBJ 206 if (opt('b') != 1) 207 (void) put(1, O_BUFF | opt('b') << 8); 208 # endif OBJ 209 # ifdef PC 210 if ( opt( 'b' ) != 1 ) { 211 putleaf( PCC_ICON , 0 , 0 212 , PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR ) , "_BUFF" ); 213 putleaf( PCC_ICON , opt( 'b' ) , 0 , PCCT_INT , (char *) 0 ); 214 putop( PCC_CALL , PCCT_INT ); 215 putdot( filename , line ); 216 } 217 # endif PC 218 inp = 0; 219 out = 0; 220 for (p = fp->chain; p != NIL; p = p->chain) { 221 if (pstrcmp(p->symbol, input->symbol) == 0) { 222 inp++; 223 continue; 224 } 225 if (pstrcmp(p->symbol, output->symbol) == 0) { 226 out++; 227 continue; 228 } 229 iop = lookup1(p->symbol); 230 if (iop == NIL || bn != cbn) { 231 error("File %s listed in program statement but not declared", p->symbol); 232 continue; 233 } 234 if (iop->class != VAR) { 235 error("File %s listed in program statement but declared as a %s", p->symbol, classes[iop->class]); 236 continue; 237 } 238 if (iop->type == NIL) 239 continue; 240 if (iop->type->class != FILET) { 241 error("File %s listed in program statement but defined as %s", 242 p->symbol, nameof(iop->type)); 243 continue; 244 } 245 # ifdef OBJ 246 (void) put(2, O_CON24, text(iop->type) ? 0 : width(iop->type->type)); 247 i = lenstr(p->symbol,0); 248 (void) put(2, O_CON24, i); 249 (void) put(2, O_LVCON, i); 250 putstr(p->symbol, 0); 251 (void) put(2, O_LV | bn<<8+INDX, (int)iop->value[NL_OFFS]); 252 (void) put(1, O_DEFNAME); 253 # endif OBJ 254 # ifdef PC 255 putleaf( PCC_ICON , 0 , 0 256 , PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR ) 257 , "_DEFNAME" ); 258 putLV( p -> symbol , bn , iop -> value[NL_OFFS] , 259 iop -> extra_flags , p2type( iop ) ); 260 putCONG( p -> symbol , strlen( p -> symbol ) 261 , LREQ ); 262 putop( PCC_CM , PCCT_INT ); 263 putleaf( PCC_ICON , strlen( p -> symbol ) 264 , 0 , PCCT_INT , (char *) 0 ); 265 putop( PCC_CM , PCCT_INT ); 266 putleaf( PCC_ICON 267 , text(iop->type) ? 0 : width(iop->type->type) 268 , 0 , PCCT_INT , (char *) 0 ); 269 putop( PCC_CM , PCCT_INT ); 270 putop( PCC_CALL , PCCT_INT ); 271 putdot( filename , line ); 272 # endif PC 273 } 274 } 275 /* 276 * Process the prog/proc/func body 277 */ 278 noreach = FALSE; 279 line = bundle->stmnt_blck.line_no; 280 statlist(blk); 281 # ifdef PTREE 282 { 283 pPointer Body = tCopy( blk ); 284 285 pDEF( PorFHeader[ nesting -- ] ).PorFBody = Body; 286 } 287 # endif PTREE 288 # ifdef OBJ 289 if (cbn== 1 && monflg != FALSE) { 290 patchfil((PTR_DCL) (cntpatch - 2), (long)cnts, 2); 291 patchfil((PTR_DCL) (nfppatch - 2), (long)pfcnt, 2); 292 } 293 # endif OBJ 294 # ifdef PC 295 if ( fp -> class == PROG && monflg ) { 296 putleaf( PCC_ICON , 0 , 0 , PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR ) 297 , "_PMFLUSH" ); 298 putleaf( PCC_ICON , cnts , 0 , PCCT_INT , (char *) 0 ); 299 putleaf( PCC_ICON , pfcnt , 0 , PCCT_INT , (char *) 0 ); 300 putop( PCC_CM , PCCT_INT ); 301 putLV( PCPCOUNT , 0 , 0 , NGLOBAL , PCCT_INT ); 302 putop( PCC_CM , PCCT_INT ); 303 putop( PCC_CALL , PCCT_INT ); 304 putdot( filename , line ); 305 } 306 # endif PC 307 /* 308 * Clean up the symbol table displays and check for unresolves 309 */ 310 line = endline; 311 if (fp->class == PROG && inp == 0 && (input->nl_flags & (NUSED|NMOD)) != 0) { 312 recovered(); 313 error("Input is used but not defined in the program statement"); 314 } 315 if (fp->class == PROG && out == 0 && (output->nl_flags & (NUSED|NMOD)) != 0) { 316 recovered(); 317 error("Output is used but not defined in the program statement"); 318 } 319 b = cbn; 320 Fp = fp; 321 chkref = (syneflg == errcnt[cbn] && opt('w') == 0)?TRUE:FALSE; 322 for (i = 0; i <= 077; i++) { 323 for (p = disptab[i]; p != NIL && (p->nl_block & 037) == b; p = p->nl_next) { 324 /* 325 * Check for variables defined 326 * but not referenced 327 */ 328 if (chkref && p->symbol != NIL) 329 switch (p->class) { 330 case FIELD: 331 /* 332 * If the corresponding record is 333 * unused, we shouldn't complain about 334 * the fields. 335 */ 336 default: 337 if ((p->nl_flags & (NUSED|NMOD)) == 0) { 338 warning(); 339 nerror("%s %s is neither used nor set", classes[p->class], p->symbol); 340 break; 341 } 342 /* 343 * If a var parameter is either 344 * modified or used that is enough. 345 */ 346 if (p->class == REF) 347 continue; 348 # ifdef OBJ 349 if ((p->nl_flags & NUSED) == 0) { 350 warning(); 351 nerror("%s %s is never used", classes[p->class], p->symbol); 352 break; 353 } 354 # endif OBJ 355 # ifdef PC 356 if (((p->nl_flags & NUSED) == 0) && ((p->extra_flags & NEXTERN) == 0)) { 357 warning(); 358 nerror("%s %s is never used", classes[p->class], p->symbol); 359 break; 360 } 361 # endif PC 362 if ((p->nl_flags & NMOD) == 0) { 363 warning(); 364 nerror("%s %s is used but never set", classes[p->class], p->symbol); 365 break; 366 } 367 case LABEL: 368 case FVAR: 369 case BADUSE: 370 break; 371 } 372 switch (p->class) { 373 case BADUSE: 374 cp = "s"; 375 /* This used to say ud_next 376 that is not a member of nl so 377 i changed it to nl_next, 378 which may be wrong */ 379 if (p->chain->nl_next == NIL) 380 cp++; 381 eholdnl(); 382 if (p->value[NL_KINDS] & ISUNDEF) 383 nerror("%s undefined on line%s", p->symbol, cp); 384 else 385 nerror("%s improperly used on line%s", p->symbol, cp); 386 pnumcnt = 10; 387 pnums((struct udinfo *) p->chain); 388 pchr('\n'); 389 break; 390 391 case FUNC: 392 case PROC: 393 # ifdef OBJ 394 if ((p->nl_flags & NFORWD)) 395 nerror("Unresolved forward declaration of %s %s", classes[p->class], p->symbol); 396 # endif OBJ 397 # ifdef PC 398 if ((p->nl_flags & NFORWD) && ((p->extra_flags & NEXTERN) == 0)) 399 nerror("Unresolved forward declaration of %s %s", classes[p->class], p->symbol); 400 # endif PC 401 break; 402 403 case LABEL: 404 if (p->nl_flags & NFORWD) 405 nerror("label %s was declared but not defined", p->symbol); 406 break; 407 case FVAR: 408 if ((p->nl_flags & NMOD) == 0) 409 nerror("No assignment to the function variable"); 410 break; 411 } 412 } 413 /* 414 * Pop this symbol 415 * table slot 416 */ 417 disptab[i] = p; 418 } 419 420 # ifdef OBJ 421 (void) put(1, O_END); 422 # endif OBJ 423 # ifdef PC 424 fp_exitcode(&eecookie); 425 stabrbrac(cbn); 426 putrbracket(ftnno); 427 fp_epilogue(&eecookie); 428 if (fp -> class != PROG) { 429 fp_formalentry(&eecookie); 430 } 431 /* 432 * declare pcp counters, if any 433 */ 434 if ( monflg && fp -> class == PROG ) { 435 putprintf( " .data" , 0 ); 436 aligndot(PCCT_INT); 437 putprintf( " .comm " , 1 ); 438 putprintf( PCPCOUNT , 1 ); 439 putprintf( ",%d" , 0 , ( cnts + 1 ) * sizeof (long) ); 440 putprintf( " .text" , 0 ); 441 } 442 # endif PC 443 #ifdef DEBUG 444 dumpnl(fp->ptr[2], (int) fp->symbol); 445 #endif 446 447 #ifdef OBJ 448 /* 449 * save the namelist for the debugger pdx 450 */ 451 452 savenl(fp->ptr[2], (int) fp->symbol); 453 #endif 454 455 /* 456 * Restore the 457 * (virtual) name list 458 * position 459 */ 460 nlfree(fp->ptr[2]); 461 /* 462 * Proc/func has been 463 * resolved 464 */ 465 fp->nl_flags &= ~NFORWD; 466 /* 467 * Patch the beg 468 * of the proc/func to 469 * the proper variable size 470 */ 471 if (Fp == NIL) 472 elineon(); 473 # ifdef OBJ 474 patchfil((PTR_DCL) var, 475 roundup(-sizes[cbn].om_max, (long) A_STACK), 2); 476 # endif OBJ 477 cbn--; 478 if (inpflist(fp->symbol)) { 479 opop('l'); 480 } 481 } 482 483 #ifdef PC 484 /* 485 * construct the long name of a function based on it's static nesting. 486 * into a caller-supplied buffer (that should be about BUFSIZ big). 487 */ 488 sextname( buffer , name , level ) 489 char buffer[]; 490 char *name; 491 int level; 492 { 493 char *starthere; 494 int i; 495 496 starthere = &buffer[0]; 497 for ( i = 1 ; i < level ; i++ ) { 498 sprintf( starthere , EXTFORMAT , enclosing[ i ] ); 499 starthere += strlen( enclosing[ i ] ) + 1; 500 } 501 sprintf( starthere , EXTFORMAT , name ); 502 starthere += strlen( name ) + 1; 503 if ( starthere >= &buffer[ BUFSIZ ] ) { 504 panic( "sextname" ); 505 } 506 } 507 508 /* 509 * code for main() 510 */ 511 #ifdef vax 512 513 codeformain() 514 { 515 putprintf(" .text" , 0 ); 516 putprintf(" .align 1" , 0 ); 517 putprintf(" .globl _main" , 0 ); 518 putprintf("_main:" , 0 ); 519 putprintf(" .word 0" , 0 ); 520 if ( opt ( 't' ) ) { 521 putprintf(" pushl $1" , 0 ); 522 } else { 523 putprintf(" pushl $0" , 0 ); 524 } 525 putprintf(" calls $1,_PCSTART" , 0 ); 526 putprintf(" movl 4(ap),__argc" , 0 ); 527 putprintf(" movl 8(ap),__argv" , 0 ); 528 putprintf(" calls $0,_program" , 0 ); 529 putprintf(" pushl $0" , 0 ); 530 putprintf(" calls $1,_PCEXIT" , 0 ); 531 } 532 #endif vax 533 534 #ifdef tahoe 535 codeformain() 536 { 537 putprintf(" .text" , 0 ); 538 putprintf(" .align 1" , 0 ); 539 putprintf(" .globl _main" , 0 ); 540 putprintf("_main:" , 0 ); 541 putprintf(" .word 0" , 0 ); 542 if ( opt ( 't' ) ) { 543 putprintf(" pushl $1" , 0 ); 544 } else { 545 putprintf(" pushl $0" , 0 ); 546 } 547 putprintf(" callf $8,_PCSTART" , 0 ); 548 putprintf(" movl 4(fp),__argc" , 0 ); 549 putprintf(" movl 8(fp),__argv" , 0 ); 550 putprintf(" callf $4,_program" , 0 ); 551 putprintf(" pushl $0" , 0 ); 552 putprintf(" callf $8,_PCEXIT" , 0 ); 553 } 554 #endif tahoe 555 556 /* 557 * prologue for the program. 558 * different because it 559 * doesn't have formal entry point 560 */ 561 #if defined(vax) || defined(tahoe) 562 prog_prologue(eecookiep) 563 struct entry_exit_cookie *eecookiep; 564 { 565 putprintf(" .text" , 0 ); 566 putprintf(" .align 1" , 0 ); 567 putprintf(" .globl _program" , 0 ); 568 putprintf("_program:" , 0 ); 569 /* 570 * register save mask 571 */ 572 eecookiep -> savlabel = (int) getlab(); 573 putprintf(" .word %s%d", 0, (int) SAVE_MASK_LABEL , eecookiep -> savlabel ); 574 } 575 576 fp_prologue(eecookiep) 577 struct entry_exit_cookie *eecookiep; 578 { 579 580 sextname( eecookiep -> extname, eecookiep -> nlp -> symbol , cbn - 1 ); 581 putprintf( " .text" , 0 ); 582 putprintf( " .align 1" , 0 ); 583 putprintf( " .globl %s%s", 0, (int) FORMALPREFIX, (int) eecookiep -> extname ); 584 putprintf( " .globl %s" , 0 , (int) eecookiep -> extname ); 585 putprintf( "%s:" , 0 , (int) eecookiep -> extname ); 586 /* 587 * register save mask 588 */ 589 eecookiep -> savlabel = (int) getlab(); 590 putprintf(" .word %s%d", 0, (int) SAVE_MASK_LABEL , eecookiep -> savlabel ); 591 } 592 #endif vax || tahoe 593 594 /* 595 * code before any user code. 596 * or code that is machine dependent. 597 */ 598 #ifdef vax 599 fp_entrycode(eecookiep) 600 struct entry_exit_cookie *eecookiep; 601 { 602 int ftnno = eecookiep -> nlp -> value[NL_ENTLOC]; 603 int proflabel = (int) getlab(); 604 int setjmp0 = (int) getlab(); 605 606 /* 607 * top of code; destination of jump from formal entry code. 608 */ 609 eecookiep -> toplabel = (int) getlab(); 610 (void) putlab( (char *) eecookiep -> toplabel ); 611 putprintf(" subl2 $%s%d,sp" , 0 , (int) FRAME_SIZE_LABEL, ftnno ); 612 if ( profflag ) { 613 /* 614 * call mcount for profiling 615 */ 616 putprintf( " moval " , 1 ); 617 putprintf( PREFIXFORMAT , 1 , (int) LABELPREFIX , proflabel ); 618 putprintf( ",r0" , 0 ); 619 putprintf( " jsb mcount" , 0 ); 620 putprintf( " .data" , 0 ); 621 putprintf( " .align 2" , 0 ); 622 (void) putlab( (char *) proflabel ); 623 putprintf( " .long 0" , 0 ); 624 putprintf( " .text" , 0 ); 625 } 626 /* 627 * if there are nested procedures that access our variables 628 * we must save the display. 629 */ 630 if ( parts[ cbn ] & NONLOCALVAR ) { 631 /* 632 * save old display 633 */ 634 putprintf( " movq %s+%d,%d(%s)" , 0 635 , (int) DISPLAYNAME , cbn * sizeof(struct dispsave) 636 , DSAVEOFFSET , (int) P2FPNAME ); 637 /* 638 * set up new display by saving AP and FP in appropriate 639 * slot in display structure. 640 */ 641 putprintf( " movq %s,%s+%d" , 0 642 , (int) P2APNAME , (int) DISPLAYNAME , cbn * sizeof(struct dispsave) ); 643 } 644 /* 645 * set underflow checking if runtime tests 646 */ 647 if ( opt( 't' ) ) { 648 putprintf( " bispsw $0xe0" , 0 ); 649 } 650 /* 651 * zero local variables if checking is on 652 * by calling blkclr( bytes of locals , starting local address ); 653 */ 654 if ( opt( 't' ) && ( -sizes[ cbn ].om_max ) > DPOFF1 ) { 655 putleaf( PCC_ICON , 0 , 0 , PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR ) 656 , "_blkclr" ); 657 putLV((char *) 0 , cbn , (int) sizes[ cbn ].om_max , NLOCAL , PCCT_CHAR ); 658 putleaf( PCC_ICON , (int) (( -sizes[ cbn ].om_max ) - DPOFF1) 659 , 0 , PCCT_INT ,(char *) 0 ); 660 putop( PCC_CM , PCCT_INT ); 661 putop( PCC_CALL , PCCT_INT ); 662 putdot( filename , line ); 663 } 664 /* 665 * set up goto vector if non-local goto to this frame 666 */ 667 if ( parts[ cbn ] & NONLOCALGOTO ) { 668 putleaf( PCC_ICON , 0 , 0 , PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR ) 669 , "_setjmp" ); 670 putLV( (char *) 0 , cbn , GOTOENVOFFSET , NLOCAL , PCCTM_PTR|PCCT_STRTY ); 671 putop( PCC_CALL , PCCT_INT ); 672 putleaf( PCC_ICON , 0 , 0 , PCCT_INT , (char *) 0 ); 673 putop( PCC_NE , PCCT_INT ); 674 putleaf( PCC_ICON , setjmp0 , 0 , PCCT_INT , (char *) 0 ); 675 putop( PCC_CBRANCH , PCCT_INT ); 676 putdot( filename , line ); 677 /* 678 * on non-local goto, setjmp returns with address to 679 * be branched to. 680 */ 681 putprintf( " jmp (r0)" , 0 ); 682 (void) putlab((char *) setjmp0); 683 } 684 } 685 #endif vax 686 687 #ifdef tahoe 688 fp_entrycode(eecookiep) 689 struct entry_exit_cookie *eecookiep; 690 { 691 int ftnno = eecookiep -> nlp -> value[NL_ENTLOC]; 692 int proflabel = (int) getlab(); 693 int setjmp0 = (int) getlab(); 694 695 /* 696 * top of code; destination of jump from formal entry code. 697 */ 698 eecookiep -> toplabel = (int) getlab(); 699 (void) putlab( (char *) eecookiep -> toplabel ); 700 putprintf(" subl3 $%s%d,fp,sp" , 0 , (int) FRAME_SIZE_LABEL, ftnno ); 701 if ( profflag ) { 702 /* 703 * call mcount for profiling 704 */ 705 putprintf( " pushal " , 1 ); 706 putprintf( PREFIXFORMAT , 0 , (int) LABELPREFIX , proflabel ); 707 putprintf( " callf $8,mcount" , 0 ); 708 putprintf( " .data" , 0 ); 709 putprintf( " .align 2" , 0 ); 710 (void) putlab( (char *) proflabel ); 711 putprintf( " .long 0" , 0 ); 712 putprintf( " .text" , 0 ); 713 } 714 /* 715 * if there are nested procedures that access our variables 716 * we must save the display. 717 */ 718 if ( parts[ cbn ] & NONLOCALVAR ) { 719 /* 720 * save old display 721 */ 722 putprintf( " movl %s+%d,%d(%s)" , 0 723 , (int) DISPLAYNAME , cbn * sizeof(struct dispsave) 724 , DSAVEOFFSET , (int) P2FPNAME ); 725 /* 726 * set up new display by saving FP in appropriate 727 * slot in display structure. 728 */ 729 putprintf( " movl %s,%s+%d" , 0 730 , (int) P2FPNAME , (int) DISPLAYNAME , cbn * sizeof(struct dispsave) ); 731 } 732 /* 733 * set underflow checking if runtime tests 734 */ 735 if ( opt( 't' ) ) { 736 putprintf( " bicpsw $0x20" , 0 ); 737 } 738 /* 739 * zero local variables if checking is on 740 * by calling blkclr( bytes of locals , starting local address ); 741 */ 742 if ( opt( 't' ) && ( -sizes[ cbn ].om_max ) > DPOFF1 ) { 743 putleaf( PCC_ICON , 0 , 0 , PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR ) 744 , "_blkclr" ); 745 putLV((char *) 0 , cbn , (int) sizes[ cbn ].om_max , NLOCAL , PCCT_CHAR ); 746 putleaf( PCC_ICON , (int) (( -sizes[ cbn ].om_max ) - DPOFF1) 747 , 0 , PCCT_INT ,(char *) 0 ); 748 putop( PCC_CM , PCCT_INT ); 749 putop( PCC_CALL , PCCT_INT ); 750 putdot( filename , line ); 751 } 752 /* 753 * set up goto vector if non-local goto to this frame 754 */ 755 if ( parts[ cbn ] & NONLOCALGOTO ) { 756 putleaf( PCC_ICON , 0 , 0 , PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR ) 757 , "_setjmp" ); 758 putLV( (char *) 0 , cbn , GOTOENVOFFSET , NLOCAL , PCCTM_PTR|PCCT_STRTY ); 759 putop( PCC_CALL , PCCT_INT ); 760 putleaf( PCC_ICON , 0 , 0 , PCCT_INT , (char *) 0 ); 761 putop( PCC_NE , PCCT_INT ); 762 putleaf( PCC_ICON , setjmp0 , 0 , PCCT_INT , (char *) 0 ); 763 putop( PCC_CBRANCH , PCCT_INT ); 764 putdot( filename , line ); 765 /* 766 * on non-local goto, setjmp returns with address to 767 * be branched to. 768 */ 769 putprintf( " jmp (r0)" , 0 ); 770 (void) putlab((char *) setjmp0); 771 } 772 } 773 #endif tahoe 774 775 #if defined(vax) || defined(tahoe) 776 fp_exitcode(eecookiep) 777 struct entry_exit_cookie *eecookiep; 778 { 779 /* 780 * if there were file variables declared at this level 781 * call PCLOSE( ap ) to clean them up. 782 */ 783 if ( dfiles[ cbn ] ) { 784 putleaf( PCC_ICON , 0 , 0 , PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR ) 785 , "_PCLOSE" ); 786 putleaf( PCC_REG , 0 , P2AP , PCCM_ADDTYPE( PCCT_CHAR , PCCTM_PTR ) , (char *) 0 ); 787 putop( PCC_CALL , PCCT_INT ); 788 putdot( filename , line ); 789 } 790 /* 791 * if this is a function, 792 * the function variable is the return value. 793 * if it's a scalar valued function, return scalar, 794 * else, return a pointer to the structure value. 795 */ 796 if ( eecookiep-> nlp -> class == FUNC ) { 797 struct nl *fvar = eecookiep-> nlp -> ptr[ NL_FVAR ]; 798 long fvartype = p2type( fvar -> type ); 799 long label; 800 char labelname[ BUFSIZ ]; 801 802 switch ( classify( fvar -> type ) ) { 803 case TBOOL: 804 case TCHAR: 805 case TINT: 806 case TSCAL: 807 case TDOUBLE: 808 case TPTR: 809 putRV( fvar -> symbol , ( fvar -> nl_block ) & 037 , 810 fvar -> value[ NL_OFFS ] , 811 fvar -> extra_flags , 812 (int) fvartype ); 813 putop( PCC_FORCE , (int) fvartype ); 814 break; 815 default: 816 label = (int) getlab(); 817 sprintf( labelname , PREFIXFORMAT , LABELPREFIX , label ); 818 putprintf( " .data" , 0 ); 819 aligndot(A_STRUCT); 820 putprintf( " .lcomm %s,%d" , 0 , 821 (int) labelname , (int) lwidth( fvar -> type ) ); 822 putprintf( " .text" , 0 ); 823 putleaf( PCC_NAME , 0 , 0 , (int) fvartype , labelname ); 824 putLV( fvar -> symbol , ( fvar -> nl_block ) & 037 , 825 fvar -> value[ NL_OFFS ] , 826 fvar -> extra_flags , 827 (int) fvartype ); 828 putstrop( PCC_STASG , (int) PCCM_ADDTYPE(fvartype, PCCTM_PTR) , 829 (int) lwidth( fvar -> type ) , 830 align( fvar -> type ) ); 831 putdot( filename , line ); 832 putleaf( PCC_ICON , 0 , 0 , (int) PCCM_ADDTYPE(fvartype, PCCTM_PTR), labelname ); 833 putop( PCC_FORCE , (int) PCCM_ADDTYPE(fvartype, PCCTM_PTR) ); 834 break; 835 } 836 putdot( filename , line ); 837 } 838 /* 839 * if there are nested procedures we must save the display. 840 */ 841 if ( parts[ cbn ] & NONLOCALVAR ) { 842 /* 843 * restore old display entry from save area 844 */ 845 #ifdef vax 846 putprintf( " movq %d(%s),%s+%d" , 0 847 , DSAVEOFFSET , (int) P2FPNAME 848 , (int) DISPLAYNAME , cbn * sizeof(struct dispsave) ); 849 #endif 850 #ifdef tahoe 851 putprintf( " movl %d(%s),%s+%d" , 0 852 , DSAVEOFFSET , (int) P2FPNAME 853 , (int) DISPLAYNAME , cbn * sizeof(struct dispsave) ); 854 #endif 855 } 856 } 857 #endif vax || tahoe 858 859 #if defined(vax) || defined(tahoe) 860 fp_epilogue(eecookiep) 861 struct entry_exit_cookie *eecookiep; 862 { 863 stabline(line); 864 putprintf(" ret" , 0 ); 865 /* 866 * set the register save mask. 867 */ 868 putprintf(" .set %s%d,0x%x", 0, 869 (int) SAVE_MASK_LABEL, eecookiep -> savlabel, savmask()); 870 } 871 #endif vax || tahoe 872 873 #if defined(vax) || defined(tahoe) 874 fp_formalentry(eecookiep) 875 struct entry_exit_cookie *eecookiep; 876 { 877 878 putprintf(" .align 1", 0); 879 putprintf("%s%s:" , 0 , (int) FORMALPREFIX , (int) eecookiep -> extname ); 880 putprintf(" .word %s%d", 0, (int) SAVE_MASK_LABEL, eecookiep -> savlabel ); 881 putleaf( PCC_ICON , 0 , 0 , PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR ) , "_FCALL" ); 882 putRV((char *) 0 , cbn , 883 eecookiep -> nlp -> value[ NL_OFFS ] + sizeof( struct formalrtn * ) , 884 NPARAM , PCCTM_PTR | PCCT_STRTY ); 885 putRV((char *) 0, cbn, eecookiep -> nlp -> value[NL_OFFS], NPARAM, PCCTM_PTR|PCCT_STRTY); 886 putop( PCC_CM , PCCT_INT ); 887 putop( PCC_CALL , PCCT_INT ); 888 putdot( filename , line ); 889 putjbr( (long) eecookiep -> toplabel ); 890 } 891 #endif vax || tahoe 892 893 #ifdef mc68000 894 895 codeformain() 896 { 897 putprintf(" .text", 0); 898 putprintf(" .globl _main", 0); 899 putprintf("_main:", 0); 900 putprintf(" link %s,#0", 0, P2FPNAME); 901 if (opt('t')) { 902 putprintf(" pea 1", 0); 903 } else { 904 putprintf(" pea 0", 0); 905 } 906 putprintf(" jbsr _PCSTART", 0); 907 putprintf(" addql #4,sp", 0); 908 putprintf(" movl %s@(8),__argc", 0, P2FPNAME); 909 putprintf(" movl %s@(12),__argv", 0, P2FPNAME); 910 putprintf(" jbsr _program", 0); 911 putprintf(" pea 0", 0); 912 putprintf(" jbsr _PCEXIT", 0); 913 } 914 915 prog_prologue(eecookiep) 916 struct entry_exit_cookie *eecookiep; 917 { 918 int ftnno = eecookiep -> nlp -> value[NL_ENTLOC]; 919 920 putprintf(" .text", 0); 921 putprintf(" .globl _program", 0); 922 putprintf("_program:", 0); 923 putprintf(" link %s,#0", 0, P2FPNAME); 924 putprintf(" addl #-%s%d,sp", 0, FRAME_SIZE_LABEL, ftnno); 925 /* touch new end of stack, to break more stack space */ 926 putprintf(" tstb sp@(-%s%d)", 0, PAGE_BREAK_LABEL, ftnno); 927 putprintf(" moveml #%s%d,sp@", 0, SAVE_MASK_LABEL, ftnno); 928 } 929 930 fp_prologue(eecookiep) 931 struct entry_exit_cookie *eecookiep; 932 { 933 int ftnno = eecookiep -> nlp -> value[NL_ENTLOC]; 934 935 sextname(eecookiep -> extname, eecookiep -> nlp -> symbol, cbn - 1); 936 putprintf(" .text", 0); 937 putprintf(" .globl %s%s", 0, FORMALPREFIX, eecookiep -> extname); 938 putprintf(" .globl %s", 0, eecookiep -> extname); 939 putprintf("%s:", 0, eecookiep -> extname); 940 putprintf(" link %s,#0", 0, P2FPNAME); 941 putprintf(" addl #-%s%d,sp", 0, FRAME_SIZE_LABEL, ftnno); 942 /* touch new end of stack, to break more stack space */ 943 putprintf(" tstb sp@(-%s%d)", 0, PAGE_BREAK_LABEL, ftnno); 944 putprintf(" moveml #%s%d,sp@", 0, SAVE_MASK_LABEL, ftnno); 945 } 946 947 fp_entrycode(eecookiep) 948 struct entry_exit_cookie *eecookiep; 949 { 950 char *proflabel = getlab(); 951 char *setjmp0 = getlab(); 952 953 /* 954 * fill in the label cookie 955 */ 956 eecookiep -> toplabel = getlab(); 957 (void) putlab(eecookiep -> toplabel); 958 /* 959 * call mcount if we are profiling. 960 */ 961 if ( profflag ) { 962 putprintf(" movl #%s%d,a0", 0, LABELPREFIX, proflabel); 963 putprintf(" jsr mcount", 0); 964 putprintf(" .data", 0); 965 putprintf(" .even", 0); 966 (void) putlab(proflabel); 967 putprintf(" .long 0", 0); 968 putprintf(" .text", 0); 969 } 970 /* 971 * if there are nested procedures that access our variables 972 * we must save the display 973 */ 974 if (parts[cbn] & NONLOCALVAR) { 975 /* 976 * save the old display 977 */ 978 putprintf(" movl %s+%d,%s@(%d)", 0, 979 DISPLAYNAME, cbn * sizeof(struct dispsave), 980 P2FPNAME, DSAVEOFFSET); 981 /* 982 * set up the new display by saving the framepointer 983 * in the display structure. 984 */ 985 putprintf(" movl %s,%s+%d", 0, 986 P2FPNAME, DISPLAYNAME, cbn * sizeof(struct dispsave)); 987 } 988 /* 989 * zero local variables if checking is on 990 * by calling blkclr( bytes of locals , starting local address ); 991 */ 992 if ( opt( 't' ) && ( -sizes[ cbn ].om_max ) > DPOFF1 ) { 993 putleaf( PCC_ICON , 0 , 0 , PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR ) 994 , "_blkclr" ); 995 putLV( 0 , cbn , sizes[ cbn ].om_max , NLOCAL , PCCT_CHAR ); 996 putleaf( PCC_ICON , ( -sizes[ cbn ].om_max ) - DPOFF1 997 , 0 , PCCT_INT , 0 ); 998 putop( PCC_CM , PCCT_INT ); 999 putop( PCC_CALL , PCCT_INT ); 1000 putdot( filename , line ); 1001 } 1002 /* 1003 * set up goto vector if non-local goto to this frame 1004 */ 1005 if ( parts[ cbn ] & NONLOCALGOTO ) { 1006 putleaf( PCC_ICON , 0 , 0 , PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR ) 1007 , "_setjmp" ); 1008 putLV( 0 , cbn , GOTOENVOFFSET , NLOCAL , PCCTM_PTR|PCCT_STRTY ); 1009 putop( PCC_CALL , PCCT_INT ); 1010 putleaf( PCC_ICON , 0 , 0 , PCCT_INT , 0 ); 1011 putop( PCC_NE , PCCT_INT ); 1012 putleaf( PCC_ICON , setjmp0 , 0 , PCCT_INT , 0 ); 1013 putop( PCC_CBRANCH , PCCT_INT ); 1014 putdot( filename , line ); 1015 /* 1016 * on non-local goto, setjmp returns with address to 1017 * be branched to. 1018 */ 1019 putprintf(" movl d0,a0", 0); 1020 putprintf(" jmp a0@", 0); 1021 (void) putlab(setjmp0); 1022 } 1023 } 1024 1025 fp_exitcode(eecookiep) 1026 struct entry_exit_cookie *eecookiep; 1027 { 1028 /* 1029 * if there were file variables declared at this level 1030 * call PCLOSE( ap ) to clean them up. 1031 */ 1032 if ( dfiles[ cbn ] ) { 1033 putleaf( PCC_ICON , 0 , 0 , PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR ) 1034 , "_PCLOSE" ); 1035 putleaf( PCC_REG , 0 , P2AP , PCCM_ADDTYPE( PCCT_CHAR , PCCTM_PTR ) , 0 ); 1036 putop( PCC_CALL , PCCT_INT ); 1037 putdot( filename , line ); 1038 } 1039 /* 1040 * if this is a function, 1041 * the function variable is the return value. 1042 * if it's a scalar valued function, return scalar, 1043 * else, return a pointer to the structure value. 1044 */ 1045 if ( eecookiep -> nlp -> class == FUNC ) { 1046 struct nl *fvar = eecookiep -> nlp -> ptr[ NL_FVAR ]; 1047 long fvartype = p2type( fvar -> type ); 1048 char *label; 1049 char labelname[ BUFSIZ ]; 1050 1051 switch ( classify( fvar -> type ) ) { 1052 case TBOOL: 1053 case TCHAR: 1054 case TINT: 1055 case TSCAL: 1056 case TDOUBLE: 1057 case TPTR: 1058 putRV( fvar -> symbol , ( fvar -> nl_block ) & 037 , 1059 fvar -> value[ NL_OFFS ] , 1060 fvar -> extra_flags , 1061 fvartype ); 1062 putop( PCC_FORCE , fvartype ); 1063 break; 1064 default: 1065 label = getlab(); 1066 sprintf( labelname , PREFIXFORMAT , LABELPREFIX , label ); 1067 putprintf(" .lcomm %s,%d", 0, 1068 labelname, lwidth(fvar -> type)); 1069 putleaf( PCC_NAME , 0 , 0 , fvartype , labelname ); 1070 putLV( fvar -> symbol , ( fvar -> nl_block ) & 037 , 1071 fvar -> value[ NL_OFFS ] , 1072 fvar -> extra_flags , 1073 fvartype ); 1074 putstrop( PCC_STASG , PCCM_ADDTYPE(fvartype, PCCTM_PTR) , 1075 lwidth( fvar -> type ) , 1076 align( fvar -> type ) ); 1077 putdot( filename , line ); 1078 putleaf( PCC_ICON , 0 , 0 , PCCM_ADDTYPE(fvartype, PCCTM_PTR), labelname ); 1079 putop( PCC_FORCE , PCCM_ADDTYPE(fvartype, PCCTM_PTR) ); 1080 break; 1081 } 1082 putdot( filename , line ); 1083 } 1084 /* 1085 * if we saved a display, we must restore it. 1086 */ 1087 if ( parts[ cbn ] & NONLOCALVAR ) { 1088 /* 1089 * restore old display entry from save area 1090 */ 1091 putprintf(" movl %s@(%d),%s+%d", 0, 1092 P2FPNAME, DSAVEOFFSET, 1093 DISPLAYNAME, cbn * sizeof(struct dispsave)); 1094 } 1095 } 1096 1097 fp_epilogue(eecookiep) 1098 struct entry_exit_cookie *eecookiep; 1099 { 1100 /* 1101 * all done by the second pass. 1102 */ 1103 } 1104 1105 fp_formalentry(eecookiep) 1106 struct entry_exit_cookie *eecookiep; 1107 { 1108 putprintf( "%s%s:" , 0 , FORMALPREFIX , eecookiep -> extname ); 1109 putprintf(" link %s,#0", 0, P2FPNAME); 1110 putprintf(" addl #-%s%d,sp", 0, FRAME_SIZE_LABEL, ftnno); 1111 /* touch new end of stack, to break more stack space */ 1112 putprintf(" tstb sp@(-%s%d)", 0, PAGE_BREAK_LABEL, ftnno); 1113 putprintf(" moveml #%s%d,sp@", 0, SAVE_MASK_LABEL, ftnno); 1114 putleaf( PCC_ICON , 0 , 0 , PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR ) , "_FCALL" ); 1115 putRV( 0 , cbn , 1116 eecookiep -> nlp -> value[ NL_OFFS ] + sizeof( struct formalrtn * ) , 1117 NPARAM , PCCTM_PTR | PCCT_STRTY ); 1118 putRV(0, cbn, eecookiep -> nlp -> value[NL_OFFS], NPARAM, PCCTM_PTR|PCCT_STRTY); 1119 putop( PCC_CM , PCCT_INT ); 1120 putop( PCC_CALL , PCCT_INT ); 1121 putdot( filename , line ); 1122 putjbr( eecookiep -> toplabel ); 1123 } 1124 #endif mc68000 1125 #endif PC 1126