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.2 (Berkeley) 11/12/86"; 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, 472 roundup(-sizes[cbn].om_max, (long) A_STACK), 2); 473 # endif OBJ 474 cbn--; 475 if (inpflist(fp->symbol)) { 476 opop('l'); 477 } 478 } 479 480 #ifdef PC 481 /* 482 * construct the long name of a function based on it's static nesting. 483 * into a caller-supplied buffer (that should be about BUFSIZ big). 484 */ 485 sextname( buffer , name , level ) 486 char buffer[]; 487 char *name; 488 int level; 489 { 490 char *starthere; 491 int i; 492 493 starthere = &buffer[0]; 494 for ( i = 1 ; i < level ; i++ ) { 495 sprintf( starthere , EXTFORMAT , enclosing[ i ] ); 496 starthere += strlen( enclosing[ i ] ) + 1; 497 } 498 sprintf( starthere , EXTFORMAT , name ); 499 starthere += strlen( name ) + 1; 500 if ( starthere >= &buffer[ BUFSIZ ] ) { 501 panic( "sextname" ); 502 } 503 } 504 505 /* 506 * code for main() 507 */ 508 #ifdef vax 509 510 codeformain() 511 { 512 putprintf(" .text" , 0 ); 513 putprintf(" .align 1" , 0 ); 514 putprintf(" .globl _main" , 0 ); 515 putprintf("_main:" , 0 ); 516 putprintf(" .word 0" , 0 ); 517 if ( opt ( 't' ) ) { 518 putprintf(" pushl $1" , 0 ); 519 } else { 520 putprintf(" pushl $0" , 0 ); 521 } 522 putprintf(" calls $1,_PCSTART" , 0 ); 523 putprintf(" movl 4(ap),__argc" , 0 ); 524 putprintf(" movl 8(ap),__argv" , 0 ); 525 putprintf(" calls $0,_program" , 0 ); 526 putprintf(" pushl $0" , 0 ); 527 putprintf(" calls $1,_PCEXIT" , 0 ); 528 } 529 530 /* 531 * prologue for the program. 532 * different because it 533 * doesn't have formal entry point 534 */ 535 prog_prologue(eecookiep) 536 struct entry_exit_cookie *eecookiep; 537 { 538 putprintf(" .text" , 0 ); 539 putprintf(" .align 1" , 0 ); 540 putprintf(" .globl _program" , 0 ); 541 putprintf("_program:" , 0 ); 542 /* 543 * register save mask 544 */ 545 eecookiep -> savlabel = (int) getlab(); 546 putprintf(" .word %s%d", 0, (int) SAVE_MASK_LABEL , eecookiep -> savlabel ); 547 } 548 549 fp_prologue(eecookiep) 550 struct entry_exit_cookie *eecookiep; 551 { 552 553 sextname( eecookiep -> extname, eecookiep -> nlp -> symbol , cbn - 1 ); 554 putprintf( " .text" , 0 ); 555 putprintf( " .align 1" , 0 ); 556 putprintf( " .globl %s%s", 0, (int) FORMALPREFIX, (int) eecookiep -> extname ); 557 putprintf( " .globl %s" , 0 , (int) eecookiep -> extname ); 558 putprintf( "%s:" , 0 , (int) eecookiep -> extname ); 559 /* 560 * register save mask 561 */ 562 eecookiep -> savlabel = (int) getlab(); 563 putprintf(" .word %s%d", 0, (int) SAVE_MASK_LABEL , eecookiep -> savlabel ); 564 } 565 566 /* 567 * code before any user code. 568 * or code that is machine dependent. 569 */ 570 fp_entrycode(eecookiep) 571 struct entry_exit_cookie *eecookiep; 572 { 573 int ftnno = eecookiep -> nlp -> value[NL_ENTLOC]; 574 int proflabel = (int) getlab(); 575 int setjmp0 = (int) getlab(); 576 577 /* 578 * top of code; destination of jump from formal entry code. 579 */ 580 eecookiep -> toplabel = (int) getlab(); 581 (void) putlab( (char *) eecookiep -> toplabel ); 582 putprintf(" subl2 $%s%d,sp" , 0 , (int) FRAME_SIZE_LABEL, ftnno ); 583 if ( profflag ) { 584 /* 585 * call mcount for profiling 586 */ 587 putprintf( " moval " , 1 ); 588 putprintf( PREFIXFORMAT , 1 , (int) LABELPREFIX , proflabel ); 589 putprintf( ",r0" , 0 ); 590 putprintf( " jsb mcount" , 0 ); 591 putprintf( " .data" , 0 ); 592 putprintf( " .align 2" , 0 ); 593 (void) putlab( (char *) proflabel ); 594 putprintf( " .long 0" , 0 ); 595 putprintf( " .text" , 0 ); 596 } 597 /* 598 * if there are nested procedures that access our variables 599 * we must save the display. 600 */ 601 if ( parts[ cbn ] & NONLOCALVAR ) { 602 /* 603 * save old display 604 */ 605 putprintf( " movq %s+%d,%d(%s)" , 0 606 , (int) DISPLAYNAME , cbn * sizeof(struct dispsave) 607 , DSAVEOFFSET , (int) P2FPNAME ); 608 /* 609 * set up new display by saving AP and FP in appropriate 610 * slot in display structure. 611 */ 612 putprintf( " movq %s,%s+%d" , 0 613 , (int) P2APNAME , (int) DISPLAYNAME , cbn * sizeof(struct dispsave) ); 614 } 615 /* 616 * set underflow checking if runtime tests 617 */ 618 if ( opt( 't' ) ) { 619 putprintf( " bispsw $0xe0" , 0 ); 620 } 621 /* 622 * zero local variables if checking is on 623 * by calling blkclr( bytes of locals , starting local address ); 624 */ 625 if ( opt( 't' ) && ( -sizes[ cbn ].om_max ) > DPOFF1 ) { 626 putleaf( PCC_ICON , 0 , 0 , PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR ) 627 , "_blkclr" ); 628 putLV((char *) 0 , cbn , (int) sizes[ cbn ].om_max , NLOCAL , PCCT_CHAR ); 629 putleaf( PCC_ICON , (int) (( -sizes[ cbn ].om_max ) - DPOFF1) 630 , 0 , PCCT_INT ,(char *) 0 ); 631 putop( PCC_CM , PCCT_INT ); 632 putop( PCC_CALL , PCCT_INT ); 633 putdot( filename , line ); 634 } 635 /* 636 * set up goto vector if non-local goto to this frame 637 */ 638 if ( parts[ cbn ] & NONLOCALGOTO ) { 639 putleaf( PCC_ICON , 0 , 0 , PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR ) 640 , "_setjmp" ); 641 putLV( (char *) 0 , cbn , GOTOENVOFFSET , NLOCAL , PCCTM_PTR|PCCT_STRTY ); 642 putop( PCC_CALL , PCCT_INT ); 643 putleaf( PCC_ICON , 0 , 0 , PCCT_INT , (char *) 0 ); 644 putop( PCC_NE , PCCT_INT ); 645 putleaf( PCC_ICON , setjmp0 , 0 , PCCT_INT , (char *) 0 ); 646 putop( PCC_CBRANCH , PCCT_INT ); 647 putdot( filename , line ); 648 /* 649 * on non-local goto, setjmp returns with address to 650 * be branched to. 651 */ 652 putprintf( " jmp (r0)" , 0 ); 653 (void) putlab((char *) setjmp0); 654 } 655 } 656 657 fp_exitcode(eecookiep) 658 struct entry_exit_cookie *eecookiep; 659 { 660 /* 661 * if there were file variables declared at this level 662 * call PCLOSE( ap ) to clean them up. 663 */ 664 if ( dfiles[ cbn ] ) { 665 putleaf( PCC_ICON , 0 , 0 , PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR ) 666 , "_PCLOSE" ); 667 putleaf( PCC_REG , 0 , P2AP , PCCM_ADDTYPE( PCCT_CHAR , PCCTM_PTR ) , (char *) 0 ); 668 putop( PCC_CALL , PCCT_INT ); 669 putdot( filename , line ); 670 } 671 /* 672 * if this is a function, 673 * the function variable is the return value. 674 * if it's a scalar valued function, return scalar, 675 * else, return a pointer to the structure value. 676 */ 677 if ( eecookiep-> nlp -> class == FUNC ) { 678 struct nl *fvar = eecookiep-> nlp -> ptr[ NL_FVAR ]; 679 long fvartype = p2type( fvar -> type ); 680 long label; 681 char labelname[ BUFSIZ ]; 682 683 switch ( classify( fvar -> type ) ) { 684 case TBOOL: 685 case TCHAR: 686 case TINT: 687 case TSCAL: 688 case TDOUBLE: 689 case TPTR: 690 putRV( fvar -> symbol , ( fvar -> nl_block ) & 037 , 691 fvar -> value[ NL_OFFS ] , 692 fvar -> extra_flags , 693 (int) fvartype ); 694 putop( PCC_FORCE , (int) fvartype ); 695 break; 696 default: 697 label = (int) getlab(); 698 sprintf( labelname , PREFIXFORMAT , LABELPREFIX , label ); 699 putprintf( " .data" , 0 ); 700 aligndot(A_STRUCT); 701 putprintf( " .lcomm %s,%d" , 0 , 702 (int) labelname , (int) lwidth( fvar -> type ) ); 703 putprintf( " .text" , 0 ); 704 putleaf( PCC_NAME , 0 , 0 , (int) fvartype , labelname ); 705 putLV( fvar -> symbol , ( fvar -> nl_block ) & 037 , 706 fvar -> value[ NL_OFFS ] , 707 fvar -> extra_flags , 708 (int) fvartype ); 709 putstrop( PCC_STASG , (int) PCCM_ADDTYPE(fvartype, PCCTM_PTR) , 710 (int) lwidth( fvar -> type ) , 711 align( fvar -> type ) ); 712 putdot( filename , line ); 713 putleaf( PCC_ICON , 0 , 0 , (int) PCCM_ADDTYPE(fvartype, PCCTM_PTR), labelname ); 714 putop( PCC_FORCE , (int) PCCM_ADDTYPE(fvartype, PCCTM_PTR) ); 715 break; 716 } 717 putdot( filename , line ); 718 } 719 /* 720 * if there are nested procedures we must save the display. 721 */ 722 if ( parts[ cbn ] & NONLOCALVAR ) { 723 /* 724 * restore old display entry from save area 725 */ 726 putprintf( " movq %d(%s),%s+%d" , 0 727 , DSAVEOFFSET , (int) P2FPNAME 728 , (int) DISPLAYNAME , cbn * sizeof(struct dispsave) ); 729 } 730 } 731 732 fp_epilogue(eecookiep) 733 struct entry_exit_cookie *eecookiep; 734 { 735 stabline(line); 736 putprintf(" ret" , 0 ); 737 /* 738 * set the register save mask. 739 */ 740 putprintf(" .set %s%d,0x%x", 0, 741 (int) SAVE_MASK_LABEL, eecookiep -> savlabel, savmask()); 742 } 743 744 fp_formalentry(eecookiep) 745 struct entry_exit_cookie *eecookiep; 746 { 747 748 putprintf(" .align 1", 0); 749 putprintf("%s%s:" , 0 , (int) FORMALPREFIX , (int) eecookiep -> extname ); 750 putprintf(" .word %s%d", 0, (int) SAVE_MASK_LABEL, eecookiep -> savlabel ); 751 putleaf( PCC_ICON , 0 , 0 , PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR ) , "_FCALL" ); 752 putRV((char *) 0 , cbn , 753 eecookiep -> nlp -> value[ NL_OFFS ] + sizeof( struct formalrtn * ) , 754 NPARAM , PCCTM_PTR | PCCT_STRTY ); 755 putRV((char *) 0, cbn, eecookiep -> nlp -> value[NL_OFFS], NPARAM, PCCTM_PTR|PCCT_STRTY); 756 putop( PCC_CM , PCCT_INT ); 757 putop( PCC_CALL , PCCT_INT ); 758 putdot( filename , line ); 759 putjbr( (long) eecookiep -> toplabel ); 760 } 761 #endif vax 762 763 #ifdef mc68000 764 765 codeformain() 766 { 767 putprintf(" .text", 0); 768 putprintf(" .globl _main", 0); 769 putprintf("_main:", 0); 770 putprintf(" link %s,#0", 0, P2FPNAME); 771 if (opt('t')) { 772 putprintf(" pea 1", 0); 773 } else { 774 putprintf(" pea 0", 0); 775 } 776 putprintf(" jbsr _PCSTART", 0); 777 putprintf(" addql #4,sp", 0); 778 putprintf(" movl %s@(8),__argc", 0, P2FPNAME); 779 putprintf(" movl %s@(12),__argv", 0, P2FPNAME); 780 putprintf(" jbsr _program", 0); 781 putprintf(" pea 0", 0); 782 putprintf(" jbsr _PCEXIT", 0); 783 } 784 785 prog_prologue(eecookiep) 786 struct entry_exit_cookie *eecookiep; 787 { 788 int ftnno = eecookiep -> nlp -> value[NL_ENTLOC]; 789 790 putprintf(" .text", 0); 791 putprintf(" .globl _program", 0); 792 putprintf("_program:", 0); 793 putprintf(" link %s,#0", 0, P2FPNAME); 794 putprintf(" addl #-%s%d,sp", 0, FRAME_SIZE_LABEL, ftnno); 795 /* touch new end of stack, to break more stack space */ 796 putprintf(" tstb sp@(-%s%d)", 0, PAGE_BREAK_LABEL, ftnno); 797 putprintf(" moveml #%s%d,sp@", 0, SAVE_MASK_LABEL, ftnno); 798 } 799 800 fp_prologue(eecookiep) 801 struct entry_exit_cookie *eecookiep; 802 { 803 int ftnno = eecookiep -> nlp -> value[NL_ENTLOC]; 804 805 sextname(eecookiep -> extname, eecookiep -> nlp -> symbol, cbn - 1); 806 putprintf(" .text", 0); 807 putprintf(" .globl %s%s", 0, FORMALPREFIX, eecookiep -> extname); 808 putprintf(" .globl %s", 0, eecookiep -> extname); 809 putprintf("%s:", 0, eecookiep -> extname); 810 putprintf(" link %s,#0", 0, P2FPNAME); 811 putprintf(" addl #-%s%d,sp", 0, FRAME_SIZE_LABEL, ftnno); 812 /* touch new end of stack, to break more stack space */ 813 putprintf(" tstb sp@(-%s%d)", 0, PAGE_BREAK_LABEL, ftnno); 814 putprintf(" moveml #%s%d,sp@", 0, SAVE_MASK_LABEL, ftnno); 815 } 816 817 fp_entrycode(eecookiep) 818 struct entry_exit_cookie *eecookiep; 819 { 820 char *proflabel = getlab(); 821 char *setjmp0 = getlab(); 822 823 /* 824 * fill in the label cookie 825 */ 826 eecookiep -> toplabel = getlab(); 827 (void) putlab(eecookiep -> toplabel); 828 /* 829 * call mcount if we are profiling. 830 */ 831 if ( profflag ) { 832 putprintf(" movl #%s%d,a0", 0, LABELPREFIX, proflabel); 833 putprintf(" jsr mcount", 0); 834 putprintf(" .data", 0); 835 putprintf(" .even", 0); 836 (void) putlab(proflabel); 837 putprintf(" .long 0", 0); 838 putprintf(" .text", 0); 839 } 840 /* 841 * if there are nested procedures that access our variables 842 * we must save the display 843 */ 844 if (parts[cbn] & NONLOCALVAR) { 845 /* 846 * save the old display 847 */ 848 putprintf(" movl %s+%d,%s@(%d)", 0, 849 DISPLAYNAME, cbn * sizeof(struct dispsave), 850 P2FPNAME, DSAVEOFFSET); 851 /* 852 * set up the new display by saving the framepointer 853 * in the display structure. 854 */ 855 putprintf(" movl %s,%s+%d", 0, 856 P2FPNAME, DISPLAYNAME, cbn * sizeof(struct dispsave)); 857 } 858 /* 859 * zero local variables if checking is on 860 * by calling blkclr( bytes of locals , starting local address ); 861 */ 862 if ( opt( 't' ) && ( -sizes[ cbn ].om_max ) > DPOFF1 ) { 863 putleaf( PCC_ICON , 0 , 0 , PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR ) 864 , "_blkclr" ); 865 putLV( 0 , cbn , sizes[ cbn ].om_max , NLOCAL , PCCT_CHAR ); 866 putleaf( PCC_ICON , ( -sizes[ cbn ].om_max ) - DPOFF1 867 , 0 , PCCT_INT , 0 ); 868 putop( PCC_CM , PCCT_INT ); 869 putop( PCC_CALL , PCCT_INT ); 870 putdot( filename , line ); 871 } 872 /* 873 * set up goto vector if non-local goto to this frame 874 */ 875 if ( parts[ cbn ] & NONLOCALGOTO ) { 876 putleaf( PCC_ICON , 0 , 0 , PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR ) 877 , "_setjmp" ); 878 putLV( 0 , cbn , GOTOENVOFFSET , NLOCAL , PCCTM_PTR|PCCT_STRTY ); 879 putop( PCC_CALL , PCCT_INT ); 880 putleaf( PCC_ICON , 0 , 0 , PCCT_INT , 0 ); 881 putop( PCC_NE , PCCT_INT ); 882 putleaf( PCC_ICON , setjmp0 , 0 , PCCT_INT , 0 ); 883 putop( PCC_CBRANCH , PCCT_INT ); 884 putdot( filename , line ); 885 /* 886 * on non-local goto, setjmp returns with address to 887 * be branched to. 888 */ 889 putprintf(" movl d0,a0", 0); 890 putprintf(" jmp a0@", 0); 891 (void) putlab(setjmp0); 892 } 893 } 894 895 fp_exitcode(eecookiep) 896 struct entry_exit_cookie *eecookiep; 897 { 898 /* 899 * if there were file variables declared at this level 900 * call PCLOSE( ap ) to clean them up. 901 */ 902 if ( dfiles[ cbn ] ) { 903 putleaf( PCC_ICON , 0 , 0 , PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR ) 904 , "_PCLOSE" ); 905 putleaf( PCC_REG , 0 , P2AP , PCCM_ADDTYPE( PCCT_CHAR , PCCTM_PTR ) , 0 ); 906 putop( PCC_CALL , PCCT_INT ); 907 putdot( filename , line ); 908 } 909 /* 910 * if this is a function, 911 * the function variable is the return value. 912 * if it's a scalar valued function, return scalar, 913 * else, return a pointer to the structure value. 914 */ 915 if ( eecookiep -> nlp -> class == FUNC ) { 916 struct nl *fvar = eecookiep -> nlp -> ptr[ NL_FVAR ]; 917 long fvartype = p2type( fvar -> type ); 918 char *label; 919 char labelname[ BUFSIZ ]; 920 921 switch ( classify( fvar -> type ) ) { 922 case TBOOL: 923 case TCHAR: 924 case TINT: 925 case TSCAL: 926 case TDOUBLE: 927 case TPTR: 928 putRV( fvar -> symbol , ( fvar -> nl_block ) & 037 , 929 fvar -> value[ NL_OFFS ] , 930 fvar -> extra_flags , 931 fvartype ); 932 putop( PCC_FORCE , fvartype ); 933 break; 934 default: 935 label = getlab(); 936 sprintf( labelname , PREFIXFORMAT , LABELPREFIX , label ); 937 putprintf(" .lcomm %s,%d", 0, 938 labelname, lwidth(fvar -> type)); 939 putleaf( PCC_NAME , 0 , 0 , fvartype , labelname ); 940 putLV( fvar -> symbol , ( fvar -> nl_block ) & 037 , 941 fvar -> value[ NL_OFFS ] , 942 fvar -> extra_flags , 943 fvartype ); 944 putstrop( PCC_STASG , PCCM_ADDTYPE(fvartype, PCCTM_PTR) , 945 lwidth( fvar -> type ) , 946 align( fvar -> type ) ); 947 putdot( filename , line ); 948 putleaf( PCC_ICON , 0 , 0 , PCCM_ADDTYPE(fvartype, PCCTM_PTR), labelname ); 949 putop( PCC_FORCE , PCCM_ADDTYPE(fvartype, PCCTM_PTR) ); 950 break; 951 } 952 putdot( filename , line ); 953 } 954 /* 955 * if we saved a display, we must restore it. 956 */ 957 if ( parts[ cbn ] & NONLOCALVAR ) { 958 /* 959 * restore old display entry from save area 960 */ 961 putprintf(" movl %s@(%d),%s+%d", 0, 962 P2FPNAME, DSAVEOFFSET, 963 DISPLAYNAME, cbn * sizeof(struct dispsave)); 964 } 965 } 966 967 fp_epilogue(eecookiep) 968 struct entry_exit_cookie *eecookiep; 969 { 970 /* 971 * all done by the second pass. 972 */ 973 } 974 975 fp_formalentry(eecookiep) 976 struct entry_exit_cookie *eecookiep; 977 { 978 putprintf( "%s%s:" , 0 , FORMALPREFIX , eecookiep -> extname ); 979 putprintf(" link %s,#0", 0, P2FPNAME); 980 putprintf(" addl #-%s%d,sp", 0, FRAME_SIZE_LABEL, ftnno); 981 /* touch new end of stack, to break more stack space */ 982 putprintf(" tstb sp@(-%s%d)", 0, PAGE_BREAK_LABEL, ftnno); 983 putprintf(" moveml #%s%d,sp@", 0, SAVE_MASK_LABEL, ftnno); 984 putleaf( PCC_ICON , 0 , 0 , PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR ) , "_FCALL" ); 985 putRV( 0 , cbn , 986 eecookiep -> nlp -> value[ NL_OFFS ] + sizeof( struct formalrtn * ) , 987 NPARAM , PCCTM_PTR | PCCT_STRTY ); 988 putRV(0, cbn, eecookiep -> nlp -> value[NL_OFFS], NPARAM, PCCTM_PTR|PCCT_STRTY); 989 putop( PCC_CM , PCCT_INT ); 990 putop( PCC_CALL , PCCT_INT ); 991 putdot( filename , line ); 992 putjbr( eecookiep -> toplabel ); 993 } 994 #endif mc68000 995 #endif PC 996