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