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