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