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