1 #ifndef lint 2 static char *sccsid ="@(#)trees.c 4.15 (Berkeley) 12/10/87"; 3 #endif 4 5 # include "pass1.h" 6 7 # include <setjmp.h> 8 9 int bdebug = 0; 10 int adebug = 0; 11 extern ddebug; 12 extern eprint(); 13 14 /* corrections when in violation of lint */ 15 16 /* some special actions, used in finding the type of nodes */ 17 # define NCVT 01 18 # define PUN 02 19 # define TYPL 04 20 # define TYPR 010 21 # define TYMATCH 040 22 # define LVAL 0100 23 # define CVTO 0200 24 # define CVTL 0400 25 # define CVTR 01000 26 # define PTMATCH 02000 27 # define OTHER 04000 28 # define NCVTR 010000 29 30 #ifndef BUG1 31 printact(t, acts) 32 NODE *t; 33 int acts; 34 { 35 static struct actions { 36 int a_bit; 37 char *a_name; 38 } actions[] = { 39 { PUN, "PUN" }, 40 { CVTL, "CVTL" }, 41 { CVTR, "CVTR" }, 42 { TYPL, "TYPL" }, 43 { TYPR, "TYPR" }, 44 { TYMATCH, "TYMATCH" }, 45 { PTMATCH, "PTMATCH" }, 46 { LVAL, "LVAL" }, 47 { CVTO, "CVTO" }, 48 { NCVT, "NCVT" }, 49 { OTHER, "OTHER" }, 50 { NCVTR, "NCVTR" }, 51 { 0 } 52 }; 53 register struct actions *p; 54 char *sep = " "; 55 56 printf("actions"); 57 for (p = actions; p->a_name; p++) 58 if (p->a_bit & acts) { 59 printf("%s%s", sep, p->a_name); 60 sep = "|"; 61 } 62 if (!bdebug) { 63 printf(" for:\n"); 64 fwalk(t, eprint, 0); 65 } else 66 putchar('\n'); 67 } 68 #endif 69 70 /* node conventions: 71 72 NAME: rval>0 is stab index for external 73 rval<0 is -inlabel number 74 lval is offset in bits 75 ICON: lval has the value 76 rval has the STAB index, or - label number, 77 if a name whose address is in the constant 78 rval = NONAME means no name 79 REG: rval is reg. identification cookie 80 81 */ 82 83 NODE * 84 buildtree( o, l, r ) register NODE *l, *r; { 85 register NODE *p, *q; 86 register actions; 87 register opty; 88 register struct symtab *sp; 89 register NODE *lr, *ll; 90 NODE *fixargs(); 91 int i; 92 93 # ifndef BUG1 94 if( bdebug ) printf( "buildtree( %s, %o, %o )\n", opst[o], l, r ); 95 # endif 96 opty = optype(o); 97 98 /* check for constants */ 99 100 if( opty == UTYPE && l->in.op == ICON ){ 101 102 switch( o ){ 103 104 case NOT: 105 if( hflag ) werror( "constant argument to NOT" ); 106 case UNARY MINUS: 107 case COMPL: 108 if( conval( l, o, l ) ) return(l); 109 break; 110 111 } 112 } 113 114 else if( o==UNARY MINUS && l->in.op==FCON ){ 115 l->fpn.fval = -l->fpn.fval; 116 return(l); 117 } 118 119 else if( o==UNARY MINUS && l->in.op==DCON ){ 120 l->dpn.dval = -l->dpn.dval; 121 return(l); 122 } 123 124 else if( o==QUEST && l->in.op==ICON ) { 125 l->in.op = FREE; 126 r->in.op = FREE; 127 if( l->tn.lval ){ 128 tfree( r->in.right ); 129 return( r->in.left ); 130 } 131 else { 132 tfree( r->in.left ); 133 return( r->in.right ); 134 } 135 } 136 137 else if( (o==ANDAND || o==OROR) && (l->in.op==ICON||r->in.op==ICON) ) goto ccwarn; 138 139 else if( opty == BITYPE && l->in.op == ICON && r->in.op == ICON ){ 140 141 switch( o ){ 142 143 case ULT: 144 case UGT: 145 case ULE: 146 case UGE: 147 case LT: 148 case GT: 149 case LE: 150 case GE: 151 case EQ: 152 case NE: 153 if( l->in.type == ENUMTY && r->in.type == ENUMTY ) 154 chkpun( p ); 155 156 case ANDAND: 157 case OROR: 158 case CBRANCH: 159 160 ccwarn: 161 if( hflag ) werror( "constant in conditional context" ); 162 163 case PLUS: 164 case MINUS: 165 case MUL: 166 case DIV: 167 case MOD: 168 case AND: 169 case OR: 170 case ER: 171 case LS: 172 case RS: 173 if( conval( l, o, r ) ) { 174 r->in.op = FREE; 175 return(l); 176 } 177 break; 178 } 179 } 180 else if (opty == BITYPE && 181 (l->in.op == FCON || l->in.op == DCON || l->in.op == ICON) && 182 (r->in.op == FCON || r->in.op == DCON || r->in.op == ICON)) { 183 if (o == PLUS || o == MINUS || o == MUL || o == DIV) { 184 extern int fpe_count; 185 extern jmp_buf gotfpe; 186 187 fpe_count = 0; 188 if (setjmp(gotfpe)) 189 goto treatfpe; 190 if (l->in.op == ICON) 191 l->dpn.dval = l->tn.lval; 192 else if (l->in.op == FCON) 193 l->dpn.dval = l->fpn.fval; 194 if (r->in.op == ICON) 195 r->dpn.dval = r->tn.lval; 196 else if (r->in.op == FCON) 197 r->dpn.dval = r->fpn.fval; 198 switch (o) { 199 200 case PLUS: 201 l->dpn.dval += r->dpn.dval; 202 break; 203 204 case MINUS: 205 l->dpn.dval -= r->dpn.dval; 206 break; 207 208 case MUL: 209 l->dpn.dval *= r->dpn.dval; 210 break; 211 212 case DIV: 213 if (r->dpn.dval == 0) 214 uerror("division by 0."); 215 else 216 l->dpn.dval /= r->dpn.dval; 217 break; 218 } 219 treatfpe: 220 if (fpe_count > 0) { 221 uerror("floating point exception in constant expression"); 222 l->dpn.dval = 1.0; /* Fairly harmless */ 223 } 224 fpe_count = -1; 225 l->in.op = DCON; 226 l->in.type = l->fn.csiz = DOUBLE; 227 r->in.op = FREE; 228 return (l); 229 } 230 } 231 232 /* it's real; we must make a new node */ 233 234 p = block( o, l, r, INT, 0, INT ); 235 236 actions = opact(p); 237 #ifndef BUG1 238 if (adebug) 239 printact(p, actions); 240 #endif 241 242 if( actions&LVAL ){ /* check left descendent */ 243 if( notlval(p->in.left) ) { 244 uerror( "illegal lhs of assignment operator" ); 245 } 246 } 247 248 if( actions & NCVTR ){ 249 p->in.left = pconvert( p->in.left ); 250 } 251 else if( !(actions & NCVT ) ){ 252 switch( opty ){ 253 254 case BITYPE: 255 p->in.right = pconvert( p->in.right ); 256 case UTYPE: 257 p->in.left = pconvert( p->in.left ); 258 259 } 260 } 261 262 if( (actions&PUN) && (o!=CAST||cflag) ){ 263 chkpun(p); 264 } 265 266 if( actions & (TYPL|TYPR) ){ 267 268 q = (actions&TYPL) ? p->in.left : p->in.right; 269 270 p->in.type = q->in.type; 271 p->fn.cdim = q->fn.cdim; 272 p->fn.csiz = q->fn.csiz; 273 } 274 275 if( actions & CVTL ) p = convert( p, CVTL ); 276 if( actions & CVTR ) p = convert( p, CVTR ); 277 if( actions & TYMATCH ) p = tymatch(p); 278 if( actions & PTMATCH ) p = ptmatch(p); 279 280 if( actions & OTHER ){ 281 l = p->in.left; 282 r = p->in.right; 283 284 switch(o){ 285 286 case NAME: 287 sp = &stab[idname]; 288 if( sp->stype == UNDEF ){ 289 #ifndef FLEXNAMES 290 uerror( "%.8s undefined", sp->sname ); 291 #else 292 uerror( "%s undefined", sp->sname ); 293 #endif 294 /* make p look reasonable */ 295 p->in.type = p->fn.cdim = p->fn.csiz = INT; 296 p->tn.rval = idname; 297 p->tn.lval = 0; 298 defid( p, SNULL ); 299 break; 300 } 301 p->in.type = sp->stype; 302 p->fn.cdim = sp->dimoff; 303 p->fn.csiz = sp->sizoff; 304 p->tn.lval = 0; 305 p->tn.rval = idname; 306 /* special case: MOETY is really an ICON... */ 307 if( p->in.type == MOETY ){ 308 p->tn.rval = NONAME; 309 p->tn.lval = sp->offset; 310 p->fn.cdim = 0; 311 p->in.type = ENUMTY; 312 p->in.op = ICON; 313 } 314 break; 315 316 case ICON: 317 p->in.type = INT; 318 p->fn.cdim = 0; 319 p->fn.csiz = INT; 320 break; 321 322 case STRING: 323 p->in.op = NAME; 324 p->in.type = CHAR+ARY; 325 p->tn.lval = 0; 326 p->tn.rval = NOLAB; 327 p->fn.cdim = curdim; 328 p->fn.csiz = CHAR; 329 break; 330 331 case FCON: 332 p->tn.lval = 0; 333 p->tn.rval = 0; 334 p->in.type = FLOAT; 335 p->fn.cdim = 0; 336 p->fn.csiz = FLOAT; 337 break; 338 339 case DCON: 340 p->tn.lval = 0; 341 p->tn.rval = 0; 342 p->in.type = DOUBLE; 343 p->fn.cdim = 0; 344 p->fn.csiz = DOUBLE; 345 break; 346 347 case STREF: 348 /* p->x turned into *(p+offset) */ 349 /* rhs must be a name; check correctness */ 350 351 i = r->tn.rval; 352 if( i<0 || ((sp= &stab[i])->sclass != MOS && sp->sclass != MOU && !(sp->sclass&FIELD)) ){ 353 uerror( "member of structure or union required" ); 354 }else 355 /* if this name is non-unique, find right one */ 356 if( stab[i].sflags & SNONUNIQ && 357 (l->in.type==PTR+STRTY || l->in.type == PTR+UNIONTY) && 358 (l->fn.csiz +1) >= 0 ){ 359 /* nonunique name && structure defined */ 360 char * memnam, * tabnam; 361 register k; 362 int j; 363 int memi; 364 j=dimtab[l->fn.csiz+1]; 365 for( ; (memi=dimtab[j]) >= 0; ++j ){ 366 tabnam = stab[memi].sname; 367 memnam = stab[i].sname; 368 # ifndef BUG1 369 if( ddebug>1 ){ 370 #ifndef FLEXNAMES 371 printf("member %.8s==%.8s?\n", 372 #else 373 printf("member %s==%s?\n", 374 #endif 375 memnam, tabnam); 376 } 377 # endif 378 if( stab[memi].sflags & SNONUNIQ ){ 379 #ifndef FLEXNAMES 380 for( k=0; k<NCHNAM; ++k ){ 381 if(*memnam++!=*tabnam) 382 goto next; 383 if(!*tabnam++) break; 384 } 385 #else 386 if (memnam != tabnam) 387 goto next; 388 #endif 389 r->tn.rval = i = memi; 390 break; 391 } 392 next: continue; 393 } 394 if( memi < 0 ) 395 #ifndef FLEXNAMES 396 uerror("illegal member use: %.8s", 397 #else 398 uerror("illegal member use: %s", 399 #endif 400 stab[i].sname); 401 } 402 else { 403 register j; 404 if( l->in.type != PTR+STRTY && l->in.type != PTR+UNIONTY ){ 405 if( stab[i].sflags & SNONUNIQ ){ 406 uerror( "nonunique name demands struct/union or struct/union pointer" ); 407 } 408 else werror( "struct/union or struct/union pointer required" ); 409 } 410 else if( (j=l->fn.csiz+1)<0 ) cerror( "undefined structure or union" ); 411 else if( !chkstr( i, dimtab[j], DECREF(l->in.type) ) ){ 412 #ifndef FLEXNAMES 413 werror( "illegal member use: %.8s", stab[i].sname ); 414 #else 415 werror( "illegal member use: %s", stab[i].sname ); 416 #endif 417 } 418 } 419 420 p = stref( p ); 421 break; 422 423 case UNARY MUL: 424 if( l->in.op == UNARY AND ){ 425 p->in.op = l->in.op = FREE; 426 p = l->in.left; 427 } 428 if( !ISPTR(l->in.type))uerror("illegal indirection"); 429 p->in.type = DECREF(l->in.type); 430 p->fn.cdim = l->fn.cdim; 431 p->fn.csiz = l->fn.csiz; 432 break; 433 434 case UNARY AND: 435 switch( l->in.op ){ 436 437 case UNARY MUL: 438 p->in.op = l->in.op = FREE; 439 p = l->in.left; 440 case NAME: 441 p->in.type = INCREF( l->in.type ); 442 p->fn.cdim = l->fn.cdim; 443 p->fn.csiz = l->fn.csiz; 444 break; 445 446 case COMOP: 447 lr = buildtree( UNARY AND, l->in.right, NIL ); 448 p->in.op = l->in.op = FREE; 449 p = buildtree( COMOP, l->in.left, lr ); 450 break; 451 452 case QUEST: 453 lr = buildtree( UNARY AND, l->in.right->in.right, NIL ); 454 ll = buildtree( UNARY AND, l->in.right->in.left, NIL ); 455 p->in.op = l->in.op = l->in.right->in.op = FREE; 456 p = buildtree( QUEST, l->in.left, buildtree( COLON, ll, lr ) ); 457 break; 458 459 # ifdef ADDROREG 460 case OREG: 461 /* OREG was built in clocal() 462 * for an auto or formal parameter 463 * now its address is being taken 464 * local code must unwind it 465 * back to PLUS/MINUS REG ICON 466 * according to local conventions 467 */ 468 { 469 extern NODE * addroreg(); 470 p->in.op = FREE; 471 p = addroreg( l ); 472 } 473 break; 474 475 # endif 476 default: 477 uerror( "unacceptable operand of &" ); 478 break; 479 } 480 break; 481 482 case LS: 483 case RS: 484 case ASG LS: 485 case ASG RS: 486 if(tsize(p->in.right->in.type, p->in.right->fn.cdim, p->in.right->fn.csiz) > SZINT) 487 p->in.right = makety(p->in.right, INT, 0, INT ); 488 break; 489 490 case RETURN: 491 case ASSIGN: 492 case CAST: 493 /* structure assignment */ 494 /* take the addresses of the two sides; then make an 495 /* operator using STASG and 496 /* the addresses of left and right */ 497 498 { 499 register TWORD t; 500 register d, s; 501 502 if( l->fn.csiz != r->fn.csiz ) uerror( "assignment of different structures" ); 503 504 r = buildtree( UNARY AND, r, NIL ); 505 t = r->in.type; 506 d = r->fn.cdim; 507 s = r->fn.csiz; 508 509 l = block( STASG, l, r, t, d, s ); 510 511 if( o == RETURN ){ 512 p->in.op = FREE; 513 p = l; 514 break; 515 } 516 517 p->in.op = UNARY MUL; 518 p->in.left = l; 519 p->in.right = NIL; 520 break; 521 } 522 case COLON: 523 /* structure colon */ 524 525 if( l->fn.csiz != r->fn.csiz ) uerror( "type clash in conditional" ); 526 break; 527 528 case CALL: 529 p->in.right = r = fixargs( p->in.right ); 530 case UNARY CALL: 531 if( !ISPTR(l->in.type)) uerror("illegal function"); 532 p->in.type = DECREF(l->in.type); 533 if( !ISFTN(p->in.type)) uerror("illegal function"); 534 p->in.type = DECREF( p->in.type ); 535 p->fn.cdim = l->fn.cdim; 536 p->fn.csiz = l->fn.csiz; 537 if( l->in.op == UNARY AND && l->in.left->in.op == NAME && 538 l->in.left->tn.rval >= 0 && l->in.left->tn.rval != NONAME && 539 ( (i=stab[l->in.left->tn.rval].sclass) == FORTRAN || i==UFORTRAN ) ){ 540 p->in.op += (FORTCALL-CALL); 541 } 542 if( p->in.type == STRTY || p->in.type == UNIONTY ){ 543 /* function returning structure */ 544 /* make function really return ptr to str., with * */ 545 546 p->in.op += STCALL-CALL; 547 p->in.type = INCREF( p->in.type ); 548 p = buildtree( UNARY MUL, p, NIL ); 549 550 } 551 break; 552 553 default: 554 cerror( "other code %d", o ); 555 } 556 557 } 558 559 if( actions & CVTO ) p = oconvert(p); 560 p = clocal(p); 561 562 # ifndef BUG1 563 if( bdebug ) fwalk( p, eprint, 0 ); 564 # endif 565 566 return(p); 567 568 } 569 570 int fpe_count = -1; 571 jmp_buf gotfpe; 572 573 fpe() { 574 if (fpe_count < 0) 575 cerror("floating point exception"); 576 ++fpe_count; 577 longjmp(gotfpe, 1); 578 } 579 580 /* 581 * Rewrite arguments in a function call. 582 * Structure arguments are massaged, single 583 * precision floating point constants are 584 * cast to double (to eliminate convert code). 585 */ 586 NODE * 587 fixargs( p ) register NODE *p; { 588 int o = p->in.op; 589 590 if( o == CM ){ 591 p->in.left = fixargs( p->in.left ); 592 p->in.right = fixargs( p->in.right ); 593 return( p ); 594 } 595 596 if( p->in.type == STRTY || p->in.type == UNIONTY ){ 597 p = block( STARG, p, NIL, p->in.type, p->fn.cdim, p->fn.csiz ); 598 p->in.left = buildtree( UNARY AND, p->in.left, NIL ); 599 p = clocal(p); 600 } 601 else if( o == FCON ) 602 p = makety(p, DOUBLE, 0, 0); 603 return( p ); 604 } 605 606 chkstr( i, j, type ) TWORD type; { 607 /* is the MOS or MOU at stab[i] OK for strict reference by a ptr */ 608 /* i has been checked to contain a MOS or MOU */ 609 /* j is the index in dimtab of the members... */ 610 int k, kk; 611 612 extern int ddebug; 613 614 # ifndef BUG1 615 #ifndef FLEXNAMES 616 if( ddebug > 1 ) printf( "chkstr( %.8s(%d), %d )\n", stab[i].sname, i, j ); 617 #else 618 if( ddebug > 1 ) printf( "chkstr( %s(%d), %d )\n", stab[i].sname, i, j ); 619 #endif 620 # endif 621 if( (k = j) < 0 ) uerror( "undefined structure or union" ); 622 else { 623 for( ; (kk = dimtab[k] ) >= 0; ++k ){ 624 if( kk >= SYMTSZ ){ 625 cerror( "gummy structure" ); 626 return(1); 627 } 628 if( kk == i ) return( 1 ); 629 switch( stab[kk].stype ){ 630 631 case STRTY: 632 case UNIONTY: 633 if( type == STRTY ) continue; /* no recursive looking for strs */ 634 if( hflag && chkstr( i, dimtab[stab[kk].sizoff+1], stab[kk].stype ) ){ 635 if( stab[kk].sname[0] == '$' ) return(0); /* $FAKE */ 636 werror( 637 #ifndef FLEXNAMES 638 "illegal member use: perhaps %.8s.%.8s?", 639 #else 640 "illegal member use: perhaps %s.%s?", 641 #endif 642 stab[kk].sname, stab[i].sname ); 643 return(1); 644 } 645 } 646 } 647 } 648 return( 0 ); 649 } 650 651 conval( p, o, q ) register NODE *p, *q; { 652 /* apply the op o to the lval part of p; if binary, rhs is val */ 653 int i, u; 654 CONSZ val; 655 656 val = q->tn.lval; 657 u = ISUNSIGNED(p->in.type) || ISUNSIGNED(q->in.type); 658 if( u && (o==LE||o==LT||o==GE||o==GT)) o += (UGE-GE); 659 660 if( p->tn.rval != NONAME && q->tn.rval != NONAME ) return(0); 661 if( q->tn.rval != NONAME && o!=PLUS ) return(0); 662 if( p->tn.rval != NONAME && o!=PLUS && o!=MINUS ) return(0); 663 664 switch( o ){ 665 666 case PLUS: 667 p->tn.lval += val; 668 if( p->tn.rval == NONAME ){ 669 p->tn.rval = q->tn.rval; 670 p->in.type = q->in.type; 671 } 672 break; 673 case MINUS: 674 p->tn.lval -= val; 675 break; 676 case MUL: 677 p->tn.lval *= val; 678 break; 679 case DIV: 680 if( val == 0 ) uerror( "division by 0" ); 681 else if ( u ) p->tn.lval = (unsigned) p->tn.lval / val; 682 else p->tn.lval /= val; 683 break; 684 case MOD: 685 if( val == 0 ) uerror( "division by 0" ); 686 else if ( u ) p->tn.lval = (unsigned) p->tn.lval % val; 687 else p->tn.lval %= val; 688 break; 689 case AND: 690 p->tn.lval &= val; 691 break; 692 case OR: 693 p->tn.lval |= val; 694 break; 695 case ER: 696 p->tn.lval ^= val; 697 break; 698 case LS: 699 i = val; 700 p->tn.lval = p->tn.lval << i; 701 break; 702 case RS: 703 i = val; 704 if ( u ) p->tn.lval = (unsigned) p->tn.lval >> i; 705 else p->tn.lval = p->tn.lval >> i; 706 break; 707 708 case UNARY MINUS: 709 p->tn.lval = - p->tn.lval; 710 break; 711 case COMPL: 712 p->tn.lval = ~p->tn.lval; 713 break; 714 case NOT: 715 p->tn.lval = !p->tn.lval; 716 break; 717 case LT: 718 p->tn.lval = p->tn.lval < val; 719 break; 720 case LE: 721 p->tn.lval = p->tn.lval <= val; 722 break; 723 case GT: 724 p->tn.lval = p->tn.lval > val; 725 break; 726 case GE: 727 p->tn.lval = p->tn.lval >= val; 728 break; 729 case ULT: 730 p->tn.lval = (p->tn.lval-val)<0; 731 break; 732 case ULE: 733 p->tn.lval = (p->tn.lval-val)<=0; 734 break; 735 case UGE: 736 p->tn.lval = (p->tn.lval-val)>=0; 737 break; 738 case UGT: 739 p->tn.lval = (p->tn.lval-val)>0; 740 break; 741 case EQ: 742 p->tn.lval = p->tn.lval == val; 743 break; 744 case NE: 745 p->tn.lval = p->tn.lval != val; 746 break; 747 default: 748 return(0); 749 } 750 return(1); 751 } 752 753 chkpun(p) register NODE *p; { 754 755 /* checks p for the existance of a pun */ 756 757 /* this is called when the op of p is ASSIGN, RETURN, CAST, COLON, or relational */ 758 759 /* one case is when enumerations are used: this applies only to lint */ 760 /* in the other case, one operand is a pointer, the other integer type */ 761 /* we check that this integer is in fact a constant zero... */ 762 763 /* in the case of ASSIGN, any assignment of pointer to integer is illegal */ 764 /* this falls out, because the LHS is never 0 */ 765 766 register NODE *q; 767 register t1, t2; 768 register d1, d2; 769 770 t1 = p->in.left->in.type; 771 t2 = p->in.right->in.type; 772 773 if( t1==ENUMTY || t2==ENUMTY ) { /* check for enumerations */ 774 if( logop( p->in.op ) && p->in.op != EQ && p->in.op != NE ) 775 werror( "comparison of enums" ); 776 if( t1==ENUMTY && t2==ENUMTY && 777 p->in.left->fn.csiz!=p->in.right->fn.csiz ) 778 werror( "enumeration type clash, operator %s", opst[p->in.op] ); 779 return; 780 } 781 782 if( ISPTR(t1) || ISARY(t1) ) q = p->in.right; 783 else q = p->in.left; 784 785 if( !ISPTR(q->in.type) && !ISARY(q->in.type) ){ 786 if( q->in.op != ICON || q->tn.lval != 0 ){ 787 werror( "illegal combination of pointer and integer, op %s", 788 opst[p->in.op] ); 789 } 790 } 791 else { 792 d1 = p->in.left->fn.cdim; 793 d2 = p->in.right->fn.cdim; 794 for( ;; ){ 795 if( t1 == t2 ) {; 796 if( p->in.left->fn.csiz != p->in.right->fn.csiz ) { 797 werror( "illegal structure pointer combination" ); 798 } 799 return; 800 } 801 if( ISARY(t1) || ISPTR(t1) ){ 802 if( !ISARY(t2) && !ISPTR(t2) ) break; 803 if( ISARY(t1) && ISARY(t2) && dimtab[d1] != dimtab[d2] ){ 804 werror( "illegal array size combination" ); 805 return; 806 } 807 if( ISARY(t1) ) ++d1; 808 if( ISARY(t2) ) ++d2; 809 } 810 else break; 811 t1 = DECREF(t1); 812 t2 = DECREF(t2); 813 } 814 werror( "illegal pointer combination" ); 815 } 816 817 } 818 819 NODE * 820 stref( p ) register NODE *p; { 821 822 TWORD t; 823 int d, s, dsc, align; 824 OFFSZ off; 825 register struct symtab *q; 826 827 /* make p->x */ 828 /* this is also used to reference automatic variables */ 829 830 q = &stab[p->in.right->tn.rval]; 831 p->in.right->in.op = FREE; 832 p->in.op = FREE; 833 p = pconvert( p->in.left ); 834 835 /* make p look like ptr to x */ 836 837 if( !ISPTR(p->in.type)){ 838 p->in.type = PTR+UNIONTY; 839 } 840 841 t = INCREF( q->stype ); 842 d = q->dimoff; 843 s = q->sizoff; 844 845 p = makety( p, t, d, s ); 846 847 /* compute the offset to be added */ 848 849 off = q->offset; 850 dsc = q->sclass; 851 852 if( dsc & FIELD ) { /* normalize offset */ 853 align = ALINT; 854 s = INT; 855 off = (off/align)*align; 856 } 857 if( off != 0 ) p = clocal( block( PLUS, p, offcon( off, t, d, s ), t, d, s ) ); 858 859 p = buildtree( UNARY MUL, p, NIL ); 860 861 /* if field, build field info */ 862 863 if( dsc & FIELD ){ 864 p = block( FLD, p, NIL, q->stype, 0, q->sizoff ); 865 p->tn.rval = PKFIELD( dsc&FLDSIZ, q->offset%align ); 866 } 867 868 return( clocal(p) ); 869 } 870 871 notlval(p) register NODE *p; { 872 873 /* return 0 if p an lvalue, 1 otherwise */ 874 875 again: 876 877 switch( p->in.op ){ 878 879 case FLD: 880 p = p->in.left; 881 goto again; 882 883 case UNARY MUL: 884 /* fix the &(a=b) bug, given that a and b are structures */ 885 if( p->in.left->in.op == STASG ) return( 1 ); 886 /* and the f().a bug, given that f returns a structure */ 887 if( p->in.left->in.op == UNARY STCALL || 888 p->in.left->in.op == STCALL ) return( 1 ); 889 case NAME: 890 case OREG: 891 if( ISARY(p->in.type) || ISFTN(p->in.type) ) return(1); 892 case REG: 893 return(0); 894 895 default: 896 return(1); 897 898 } 899 900 } 901 902 NODE * 903 bcon( i ){ /* make a constant node with value i */ 904 register NODE *p; 905 906 p = block( ICON, NIL, NIL, INT, 0, INT ); 907 p->tn.lval = i; 908 p->tn.rval = NONAME; 909 return( clocal(p) ); 910 } 911 912 NODE * 913 bpsize(p) register NODE *p; { 914 return( offcon( psize(p), p->in.type, p->fn.cdim, p->fn.csiz ) ); 915 } 916 917 OFFSZ 918 psize( p ) NODE *p; { 919 /* p is a node of type pointer; psize returns the 920 size of the thing pointed to */ 921 922 if( !ISPTR(p->in.type) ){ 923 uerror( "pointer required"); 924 return( SZINT ); 925 } 926 /* note: no pointers to fields */ 927 return( tsize( DECREF(p->in.type), p->fn.cdim, p->fn.csiz ) ); 928 } 929 930 NODE * 931 convert( p, f ) register NODE *p; { 932 /* convert an operand of p 933 f is either CVTL or CVTR 934 operand has type int, and is converted by the size of the other side 935 */ 936 937 register NODE *q, *r; 938 939 q = (f==CVTL)?p->in.left:p->in.right; 940 941 r = block( PMCONV, 942 q, bpsize(f==CVTL?p->in.right:p->in.left), INT, 0, INT ); 943 r = clocal(r); 944 if( f == CVTL ) 945 p->in.left = r; 946 else 947 p->in.right = r; 948 return(p); 949 950 } 951 952 #ifndef econvert 953 econvert( p ) register NODE *p; { 954 955 /* change enums to ints, or appropriate types */ 956 957 register TWORD ty; 958 959 if( (ty=BTYPE(p->in.type)) == ENUMTY || ty == MOETY ) { 960 if( dimtab[ p->fn.csiz ] == SZCHAR ) ty = CHAR; 961 else if( dimtab[ p->fn.csiz ] == SZINT ) ty = INT; 962 else if( dimtab[ p->fn.csiz ] == SZSHORT ) ty = SHORT; 963 else ty = LONG; 964 ty = ctype( ty ); 965 p->fn.csiz = ty; 966 MODTYPE(p->in.type,ty); 967 if( p->in.op == ICON && ty != LONG ) p->in.type = p->fn.csiz = INT; 968 } 969 } 970 #endif 971 972 NODE * 973 pconvert( p ) register NODE *p; { 974 975 /* if p should be changed into a pointer, do so */ 976 977 if( ISARY( p->in.type) ){ 978 p->in.type = DECREF( p->in.type ); 979 ++p->fn.cdim; 980 return( buildtree( UNARY AND, p, NIL ) ); 981 } 982 if( ISFTN( p->in.type) ) 983 return( buildtree( UNARY AND, p, NIL ) ); 984 985 return( p ); 986 } 987 988 NODE * 989 oconvert(p) register NODE *p; { 990 /* convert the result itself: used for pointer and unsigned */ 991 992 switch(p->in.op) { 993 994 case LE: 995 case LT: 996 case GE: 997 case GT: 998 if( ISUNSIGNED(p->in.left->in.type) || ISUNSIGNED(p->in.right->in.type) ) p->in.op += (ULE-LE); 999 case EQ: 1000 case NE: 1001 return( p ); 1002 1003 case MINUS: 1004 return( clocal( block( PVCONV, 1005 p, bpsize(p->in.left), INT, 0, INT ) ) ); 1006 } 1007 1008 cerror( "illegal oconvert: %d", p->in.op ); 1009 1010 return(p); 1011 } 1012 1013 NODE * 1014 ptmatch(p) register NODE *p; { 1015 1016 /* makes the operands of p agree; they are 1017 either pointers or integers, by this time */ 1018 /* with MINUS, the sizes must be the same */ 1019 /* with COLON, the types must be the same */ 1020 1021 TWORD t1, t2, t; 1022 int o, d2, d, s2, s; 1023 1024 o = p->in.op; 1025 t = t1 = p->in.left->in.type; 1026 t2 = p->in.right->in.type; 1027 d = p->in.left->fn.cdim; 1028 d2 = p->in.right->fn.cdim; 1029 s = p->in.left->fn.csiz; 1030 s2 = p->in.right->fn.csiz; 1031 1032 switch( o ){ 1033 1034 case ASSIGN: 1035 case RETURN: 1036 case CAST: 1037 { break; } 1038 1039 case MINUS: 1040 { if( psize(p->in.left) != psize(p->in.right) ){ 1041 uerror( "illegal pointer subtraction"); 1042 } 1043 break; 1044 } 1045 case COLON: 1046 { if( t1 != t2 ) uerror( "illegal types in :"); 1047 break; 1048 } 1049 default: /* must work harder: relationals or comparisons */ 1050 1051 if( !ISPTR(t1) ){ 1052 t = t2; 1053 d = d2; 1054 s = s2; 1055 break; 1056 } 1057 if( !ISPTR(t2) ){ 1058 break; 1059 } 1060 1061 /* both are pointers */ 1062 if( talign(t2,s2) < talign(t,s) ){ 1063 t = t2; 1064 s = s2; 1065 } 1066 break; 1067 } 1068 1069 p->in.left = makety( p->in.left, t, d, s ); 1070 p->in.right = makety( p->in.right, t, d, s ); 1071 if( o!=MINUS && !logop(o) ){ 1072 1073 p->in.type = t; 1074 p->fn.cdim = d; 1075 p->fn.csiz = s; 1076 } 1077 1078 return(clocal(p)); 1079 } 1080 1081 int tdebug = 0; 1082 1083 NODE * 1084 tymatch(p) register NODE *p; { 1085 1086 /* satisfy the types of various arithmetic binary ops */ 1087 1088 /* rules are: 1089 if assignment, type of LHS 1090 if any float or doubles, make double 1091 if any longs, make long 1092 otherwise, make int 1093 if either operand is unsigned, the result is... 1094 */ 1095 1096 register TWORD t1, t2, t, tu; 1097 register o, u; 1098 1099 o = p->in.op; 1100 1101 t1 = p->in.left->in.type; 1102 t2 = p->in.right->in.type; 1103 if( (t1==UNDEF || t2==UNDEF) && o!=CAST ) 1104 uerror("void type illegal in expression"); 1105 1106 u = 0; 1107 if( ISUNSIGNED(t1) ){ 1108 u = 1; 1109 t1 = DEUNSIGN(t1); 1110 } 1111 if( ISUNSIGNED(t2) ){ 1112 u = 1; 1113 t2 = DEUNSIGN(t2); 1114 } 1115 1116 if( ( t1 == CHAR || t1 == SHORT ) && o!= RETURN ) t1 = INT; 1117 if( t2 == CHAR || t2 == SHORT ) t2 = INT; 1118 1119 #ifdef SPRECC 1120 if( t1 == DOUBLE || t2 == DOUBLE ) 1121 t = DOUBLE; 1122 else if( t1 == FLOAT || t2 == FLOAT ) 1123 t = FLOAT; 1124 #else 1125 if (t1 == DOUBLE || t1 == FLOAT || t2 == DOUBLE || t2 == FLOAT) 1126 t = DOUBLE; 1127 #endif 1128 else if( t1==LONG || t2==LONG ) t = LONG; 1129 else t = INT; 1130 1131 if( o == ASSIGN || o == CAST || o == RETURN ){ 1132 tu = p->in.left->in.type; 1133 t = t1; 1134 } 1135 else { 1136 tu = (u && UNSIGNABLE(t))?ENUNSIGN(t):t; 1137 } 1138 1139 /* because expressions have values that are at least as wide 1140 as INT or UNSIGNED, the only conversions needed 1141 are those involving FLOAT/DOUBLE, and those 1142 from LONG to INT and ULONG to UNSIGNED */ 1143 1144 if( t != t1 && ! asgop(o) ) 1145 p->in.left = makety( p->in.left, tu, 0, (int)tu ); 1146 1147 if( t != t2 || o==CAST) 1148 if ( tu == ENUMTY ) {/* always asgop */ 1149 p->in.right = makety( p->in.right, INT, 0, INT ); 1150 p->in.right->in.type = tu; 1151 p->in.right->fn.cdim = p->in.left->fn.cdim; 1152 p->in.right->fn.csiz = p->in.left->fn.csiz; 1153 } 1154 else 1155 p->in.right = makety( p->in.right, tu, 0, (int)tu ); 1156 1157 if( asgop(o) ){ 1158 p->in.type = p->in.left->in.type; 1159 p->fn.cdim = p->in.left->fn.cdim; 1160 p->fn.csiz = p->in.left->fn.csiz; 1161 } 1162 else if( !logop(o) ){ 1163 p->in.type = tu; 1164 p->fn.cdim = 0; 1165 p->fn.csiz = t; 1166 } 1167 1168 # ifndef BUG1 1169 if( tdebug ) printf( "tymatch(%o): %o %s %o => %o\n",p,t1,opst[o],t2,tu ); 1170 # endif 1171 1172 return(p); 1173 } 1174 1175 NODE * 1176 makety( p, t, d, s ) register NODE *p; TWORD t; { 1177 /* make p into type t by inserting a conversion */ 1178 1179 if( p->in.type == ENUMTY && p->in.op == ICON ) econvert(p); 1180 if( t == p->in.type ){ 1181 p->fn.cdim = d; 1182 p->fn.csiz = s; 1183 return( p ); 1184 } 1185 1186 if( t & TMASK ){ 1187 /* non-simple type */ 1188 return( block( PCONV, p, NIL, t, d, s ) ); 1189 } 1190 1191 if( p->in.op == ICON ){ 1192 if (t == DOUBLE) { 1193 p->in.op = DCON; 1194 if (ISUNSIGNED(p->in.type)) 1195 p->dpn.dval = /* (unsigned CONSZ) */ p->tn.lval; 1196 else 1197 p->dpn.dval = p->tn.lval; 1198 p->in.type = p->fn.csiz = t; 1199 return (clocal(p)); 1200 } 1201 if (t == FLOAT) { 1202 p->in.op = FCON; 1203 if( ISUNSIGNED(p->in.type) ){ 1204 p->fpn.fval = /* (unsigned CONSZ) */ p->tn.lval; 1205 } 1206 else { 1207 p->fpn.fval = p->tn.lval; 1208 } 1209 1210 p->in.type = p->fn.csiz = t; 1211 return( clocal(p) ); 1212 } 1213 } 1214 else if (p->in.op == FCON && t == DOUBLE) { 1215 double db; 1216 1217 p->in.op = DCON; 1218 db = p->fpn.fval; 1219 p->dpn.dval = db; 1220 p->in.type = p->fn.csiz = t; 1221 return (clocal(p)); 1222 } else if (p->in.op == DCON && t == FLOAT) { 1223 float fl; 1224 1225 p->in.op = FCON; 1226 fl = p->dpn.dval; 1227 #ifdef notdef 1228 if (fl != p->dpn.dval) 1229 werror("float conversion loses precision"); 1230 #endif 1231 p->fpn.fval = fl; 1232 p->in.type = p->fn.csiz = t; 1233 return (clocal(p)); 1234 } 1235 1236 return( clocal( block( SCONV, p, NIL, t, d, s ) ) ); 1237 1238 } 1239 1240 NODE * 1241 block( o, l, r, t, d, s ) register NODE *l, *r; TWORD t; { 1242 1243 register NODE *p; 1244 1245 p = talloc(); 1246 p->in.op = o; 1247 p->in.left = l; 1248 p->in.right = r; 1249 p->in.type = t; 1250 p->fn.cdim = d; 1251 p->fn.csiz = s; 1252 return(p); 1253 } 1254 1255 icons(p) register NODE *p; { 1256 /* if p is an integer constant, return its value */ 1257 int val; 1258 1259 if( p->in.op != ICON ){ 1260 uerror( "constant expected"); 1261 val = 1; 1262 } 1263 else { 1264 val = p->tn.lval; 1265 if( val != p->tn.lval ) uerror( "constant too big for cross-compiler" ); 1266 } 1267 tfree( p ); 1268 return(val); 1269 } 1270 1271 /* the intent of this table is to examine the 1272 operators, and to check them for 1273 correctness. 1274 1275 The table is searched for the op and the 1276 modified type (where this is one of the 1277 types INT (includes char and short), LONG, 1278 DOUBLE (includes FLOAT), and POINTER 1279 1280 The default action is to make the node type integer 1281 1282 The actions taken include: 1283 PUN check for puns 1284 CVTL convert the left operand 1285 CVTR convert the right operand 1286 TYPL the type is determined by the left operand 1287 TYPR the type is determined by the right operand 1288 TYMATCH force type of left and right to match, by inserting conversions 1289 PTMATCH like TYMATCH, but for pointers 1290 LVAL left operand must be lval 1291 CVTO convert the op 1292 NCVT do not convert the operands 1293 OTHER handled by code 1294 NCVTR convert the left operand, not the right... 1295 1296 */ 1297 1298 # define MINT 01 /* integer */ 1299 # define MDBI 02 /* integer or double */ 1300 # define MSTR 04 /* structure */ 1301 # define MPTR 010 /* pointer */ 1302 # define MPTI 020 /* pointer or integer */ 1303 # define MENU 040 /* enumeration variable or member */ 1304 # define MVOID 0100000 /* void type */ 1305 1306 opact( p ) NODE *p; { 1307 1308 register mt12, mt1, mt2, o; 1309 1310 mt1 = mt2 = mt12 = 0; 1311 1312 switch( optype(o=p->in.op) ){ 1313 1314 case BITYPE: 1315 mt2 = moditype( p->in.right->in.type ); 1316 case UTYPE: 1317 mt1 = moditype( p->in.left->in.type ); 1318 break; 1319 1320 } 1321 1322 if( ((mt1 | mt2) & MVOID) && 1323 o != COMOP && 1324 !(o == CAST && (mt1 & MVOID)) ){ 1325 /* if lhs of RETURN is void, grammar will complain */ 1326 if( o != RETURN ) 1327 uerror( "value of void expression used" ); 1328 return( NCVT ); 1329 } 1330 mt1 &= ~MVOID; 1331 mt2 &= ~MVOID; 1332 mt12 = mt1 & mt2; 1333 1334 switch( o ){ 1335 1336 case NAME : 1337 case STRING : 1338 case ICON : 1339 case FCON : 1340 case DCON : 1341 case CALL : 1342 case UNARY CALL: 1343 case UNARY MUL: 1344 { return( OTHER ); } 1345 case UNARY MINUS: 1346 if( mt1 & MDBI ) return( TYPL ); 1347 break; 1348 1349 case COMPL: 1350 if( mt1 & MINT ) return( TYPL ); 1351 break; 1352 1353 case UNARY AND: 1354 { return( NCVT+OTHER ); } 1355 case INIT: 1356 case CM: 1357 return( 0 ); 1358 1359 case NOT: 1360 case CBRANCH: 1361 if( mt1 & MSTR ) break; 1362 return( 0 ); 1363 1364 case ANDAND: 1365 case OROR: 1366 if( (mt1 & MSTR) || (mt2 & MSTR) ) break; 1367 return( 0 ); 1368 1369 case MUL: 1370 case DIV: 1371 if( mt12 & MDBI ) return( TYMATCH ); 1372 break; 1373 1374 case MOD: 1375 case AND: 1376 case OR: 1377 case ER: 1378 if( mt12 & MINT ) return( TYMATCH ); 1379 break; 1380 1381 case LS: 1382 case RS: 1383 if( mt12 & MINT ) return( TYMATCH+OTHER ); 1384 break; 1385 1386 case EQ: 1387 case NE: 1388 case LT: 1389 case LE: 1390 case GT: 1391 case GE: 1392 if( (mt1&MENU)||(mt2&MENU) ) return( PTMATCH+PUN+NCVT ); 1393 if( mt12 & MDBI ) return( TYMATCH+CVTO ); 1394 else if( mt12 & MPTR ) return( PTMATCH+PUN ); 1395 else if( mt12 & MPTI ) return( PTMATCH+PUN ); 1396 else break; 1397 1398 case QUEST: 1399 case COMOP: 1400 if( mt2&MENU ) return( TYPR+NCVTR ); 1401 return( TYPR ); 1402 1403 case STREF: 1404 return( NCVTR+OTHER ); 1405 1406 case FORCE: 1407 return( TYPL ); 1408 1409 case COLON: 1410 if( mt12 & MENU ) return( NCVT+PUN+PTMATCH ); 1411 else if( mt12 & MDBI ) return( TYMATCH ); 1412 else if( mt12 & MPTR ) return( TYPL+PTMATCH+PUN ); 1413 else if( (mt1&MINT) && (mt2&MPTR) ) return( TYPR+PUN ); 1414 else if( (mt1&MPTR) && (mt2&MINT) ) return( TYPL+PUN ); 1415 else if( mt12 & MSTR ) return( NCVT+TYPL+OTHER ); 1416 break; 1417 1418 case ASSIGN: 1419 case RETURN: 1420 if( mt12 & MSTR ) return( LVAL+NCVT+TYPL+OTHER ); 1421 else if( (mt1&MENU)||(mt2&MENU) ) return( LVAL+NCVT+TYPL+PTMATCH+PUN ); 1422 case CAST: 1423 if(o==CAST && mt1==0)return(TYPL+TYMATCH); 1424 else if( mt12 & MDBI ) return( TYPL+LVAL+TYMATCH ); 1425 else if( mt2 == 0 && 1426 ( p->in.right->in.op == CALL || 1427 p->in.right->in.op == UNARY CALL)) break; 1428 else if( mt1 & MPTR ) return( LVAL+PTMATCH+PUN ); 1429 else if( mt12 & MPTI ) return( TYPL+LVAL+TYMATCH+PUN ); 1430 break; 1431 1432 case ASG LS: 1433 case ASG RS: 1434 if( mt12 & MINT ) return( TYPL+LVAL+OTHER ); 1435 break; 1436 1437 case ASG MUL: 1438 case ASG DIV: 1439 if( mt12 & MDBI ) return( LVAL+TYMATCH ); 1440 break; 1441 1442 case ASG MOD: 1443 case ASG AND: 1444 case ASG OR: 1445 case ASG ER: 1446 if( mt12 & MINT ) return( LVAL+TYMATCH ); 1447 break; 1448 1449 case ASG PLUS: 1450 case ASG MINUS: 1451 case INCR: 1452 case DECR: 1453 if( mt12 & MDBI ) return( TYMATCH+LVAL ); 1454 else if( (mt1&MPTR) && (mt2&MINT) ) return( TYPL+LVAL+CVTR ); 1455 break; 1456 1457 case MINUS: 1458 if( mt12 & MPTR ) return( CVTO+PTMATCH+PUN ); 1459 if( mt2 & MPTR ) break; 1460 case PLUS: 1461 if( mt12 & MDBI ) return( TYMATCH ); 1462 else if( (mt1&MPTR) && (mt2&MINT) ) return( TYPL+CVTR ); 1463 else if( (mt1&MINT) && (mt2&MPTR) ) return( TYPR+CVTL ); 1464 1465 } 1466 if( mt12 == MSTR ) 1467 uerror( "%s is not a permitted struct/union operation", opst[o] ); 1468 else 1469 uerror( "operands of %s have incompatible types", opst[o] ); 1470 return( NCVT ); 1471 } 1472 1473 moditype( ty ) TWORD ty; { 1474 1475 switch( ty ){ 1476 1477 case TVOID: 1478 return( MPTR ); 1479 case UNDEF: 1480 return( MVOID ); 1481 case ENUMTY: 1482 case MOETY: 1483 return( MENU|MINT|MDBI|MPTI ); /* enums are ints */ 1484 1485 case STRTY: 1486 case UNIONTY: 1487 return( MSTR ); 1488 1489 case CHAR: 1490 case SHORT: 1491 case UCHAR: 1492 case USHORT: 1493 return( MINT|MPTI|MDBI ); 1494 case UNSIGNED: 1495 case ULONG: 1496 case INT: 1497 case LONG: 1498 return( MINT|MDBI|MPTI ); 1499 case FLOAT: 1500 case DOUBLE: 1501 return( MDBI ); 1502 default: 1503 return( MPTR|MPTI ); 1504 1505 } 1506 } 1507 1508 NODE * 1509 doszof( p ) register NODE *p; { 1510 /* do sizeof p */ 1511 int i; 1512 1513 /* whatever is the meaning of this if it is a bitfield? */ 1514 i = tsize( p->in.type, p->fn.cdim, p->fn.csiz )/SZCHAR; 1515 1516 tfree(p); 1517 if( i <= 0 ) werror( "sizeof returns 0" ); 1518 return( bcon( i ) ); 1519 } 1520 1521 # ifndef BUG2 1522 eprint( p, down, a, b ) register NODE *p; int *a, *b; { 1523 register ty; 1524 1525 *a = *b = down+1; 1526 while( down > 1 ){ 1527 printf( "\t" ); 1528 down -= 2; 1529 } 1530 if( down ) printf( " " ); 1531 1532 ty = optype( p->in.op ); 1533 1534 printf("%o) %s, ", p, opst[p->in.op] ); 1535 if( ty == LTYPE ){ 1536 printf( CONFMT, p->tn.lval ); 1537 printf( ", %d, ", p->tn.rval ); 1538 } 1539 tprint( p->in.type ); 1540 printf( ", %d, %d\n", p->fn.cdim, p->fn.csiz ); 1541 } 1542 # endif 1543 1544 prtdcon( p ) register NODE *p; { 1545 int o = p->in.op, i; 1546 1547 if( o == DCON || o == FCON ){ 1548 locctr( DATA ); 1549 defalign( o == DCON ? ALDOUBLE : ALFLOAT ); 1550 deflab( i = getlab() ); 1551 if( o == FCON ) 1552 fincode( p->fpn.fval, SZFLOAT ); 1553 else 1554 fincode( p->dpn.dval, SZDOUBLE ); 1555 p->tn.lval = 0; 1556 p->tn.rval = -i; 1557 p->in.type = (o == DCON ? DOUBLE : FLOAT); 1558 p->in.op = NAME; 1559 } 1560 } 1561 1562 1563 int edebug = 0; 1564 ecomp( p ) register NODE *p; { 1565 # ifndef BUG2 1566 if( edebug ) fwalk( p, eprint, 0 ); 1567 # endif 1568 if( !reached ){ 1569 werror( "statement not reached" ); 1570 reached = 1; 1571 } 1572 p = optim(p); 1573 walkf( p, prtdcon ); 1574 locctr( PROG ); 1575 ecode( p ); 1576 tfree(p); 1577 } 1578 1579 # ifdef STDPRTREE 1580 # ifndef ONEPASS 1581 1582 prtree(p) register NODE *p; { 1583 1584 register struct symtab *q; 1585 register ty; 1586 1587 # ifdef MYPRTREE 1588 MYPRTREE(p); /* local action can be taken here; then return... */ 1589 #endif 1590 1591 ty = optype(p->in.op); 1592 1593 printf( "%d\t", p->in.op ); 1594 1595 if( ty == LTYPE ) { 1596 printf( CONFMT, p->tn.lval ); 1597 printf( "\t" ); 1598 } 1599 if( ty != BITYPE ) { 1600 if( p->in.op == NAME || p->in.op == ICON ) printf( "0\t" ); 1601 else printf( "%d\t", p->tn.rval ); 1602 } 1603 1604 printf( "%o\t", p->in.type ); 1605 1606 /* handle special cases */ 1607 1608 switch( p->in.op ){ 1609 1610 case NAME: 1611 case ICON: 1612 /* print external name */ 1613 if( p->tn.rval == NONAME ) printf( "\n" ); 1614 else if( p->tn.rval >= 0 ){ 1615 q = &stab[p->tn.rval]; 1616 printf( "%s\n", exname(q->sname) ); 1617 } 1618 else { /* label */ 1619 printf( LABFMT, -p->tn.rval ); 1620 } 1621 break; 1622 1623 case STARG: 1624 case STASG: 1625 case STCALL: 1626 case UNARY STCALL: 1627 /* print out size */ 1628 /* use lhs size, in order to avoid hassles with the structure `.' operator */ 1629 1630 /* note: p->in.left not a field... */ 1631 printf( CONFMT, (CONSZ) tsize( STRTY, p->in.left->fn.cdim, p->in.left->fn.csiz ) ); 1632 printf( "\t%d\t\n", talign( STRTY, p->in.left->fn.csiz ) ); 1633 break; 1634 1635 default: 1636 printf( "\n" ); 1637 } 1638 1639 if( ty != LTYPE ) prtree( p->in.left ); 1640 if( ty == BITYPE ) prtree( p->in.right ); 1641 1642 } 1643 1644 # else 1645 1646 p2tree(p) register NODE *p; { 1647 register ty; 1648 1649 # ifdef MYP2TREE 1650 MYP2TREE(p); /* local action can be taken here; then return... */ 1651 # endif 1652 1653 ty = optype(p->in.op); 1654 1655 switch( p->in.op ){ 1656 1657 case NAME: 1658 case ICON: 1659 #ifndef FLEXNAMES 1660 if( p->tn.rval == NONAME ) p->in.name[0] = '\0'; 1661 #else 1662 if( p->tn.rval == NONAME ) p->in.name = ""; 1663 #endif 1664 else if( p->tn.rval >= 0 ){ /* copy name from exname */ 1665 register char *cp; 1666 register i; 1667 cp = exname( stab[p->tn.rval].sname ); 1668 #ifndef FLEXNAMES 1669 for( i=0; i<NCHNAM; ++i ) p->in.name[i] = *cp++; 1670 #else 1671 p->in.name = tstr(cp); 1672 #endif 1673 } 1674 #ifndef FLEXNAMES 1675 else sprintf( p->in.name, LABFMT, -p->tn.rval ); 1676 #else 1677 else { 1678 char temp[32]; 1679 sprintf( temp, LABFMT, -p->tn.rval ); 1680 p->in.name = tstr(temp); 1681 } 1682 #endif 1683 break; 1684 1685 case STARG: 1686 case STASG: 1687 case STCALL: 1688 case UNARY STCALL: 1689 /* set up size parameters */ 1690 p->stn.stsize = (tsize(STRTY,p->in.left->fn.cdim,p->in.left->fn.csiz)+SZCHAR-1)/SZCHAR; 1691 p->stn.stalign = talign(STRTY,p->in.left->fn.csiz)/SZCHAR; 1692 break; 1693 1694 case REG: 1695 rbusy( p->tn.rval, p->in.type ); 1696 default: 1697 #ifndef FLEXNAMES 1698 p->in.name[0] = '\0'; 1699 #else 1700 p->in.name = ""; 1701 #endif 1702 } 1703 1704 p->in.rall = NOPREF; 1705 1706 if( ty != LTYPE ) p2tree( p->in.left ); 1707 if( ty == BITYPE ) p2tree( p->in.right ); 1708 } 1709 1710 # endif 1711 # endif 1712