1 #ifndef lint 2 static char *sccsid ="@(#)trees.c 4.16 (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 /* rob pike says this is obnoxious... 775 if( logop( p->in.op ) && p->in.op != EQ && p->in.op != NE ) 776 werror( "comparison of enums" ); */ 777 if( t1==ENUMTY && t2==ENUMTY ) { 778 if ( p->in.left->fn.csiz!=p->in.right->fn.csiz ) 779 werror( "enumeration type clash, operator %s", opst[p->in.op] ); 780 return; 781 } 782 if ( t1 == ENUMTY ) t1 = INT; 783 if ( t2 == ENUMTY ) t2 = INT; 784 } 785 786 if( ISPTR(t1) || ISARY(t1) ) q = p->in.right; 787 else q = p->in.left; 788 789 if( !ISPTR(q->in.type) && !ISARY(q->in.type) ){ 790 if( q->in.op != ICON || q->tn.lval != 0 ){ 791 werror( "illegal combination of pointer and integer, op %s", 792 opst[p->in.op] ); 793 } 794 } 795 else { 796 d1 = p->in.left->fn.cdim; 797 d2 = p->in.right->fn.cdim; 798 for( ;; ){ 799 if( t1 == t2 ) {; 800 if( p->in.left->fn.csiz != p->in.right->fn.csiz ) { 801 werror( "illegal structure pointer combination" ); 802 } 803 return; 804 } 805 if( ISARY(t1) || ISPTR(t1) ){ 806 if( !ISARY(t2) && !ISPTR(t2) ) break; 807 if( ISARY(t1) && ISARY(t2) && dimtab[d1] != dimtab[d2] ){ 808 werror( "illegal array size combination" ); 809 return; 810 } 811 if( ISARY(t1) ) ++d1; 812 if( ISARY(t2) ) ++d2; 813 } 814 else break; 815 t1 = DECREF(t1); 816 t2 = DECREF(t2); 817 } 818 werror( "illegal pointer combination" ); 819 } 820 821 } 822 823 NODE * 824 stref( p ) register NODE *p; { 825 826 TWORD t; 827 int d, s, dsc, align; 828 OFFSZ off; 829 register struct symtab *q; 830 831 /* make p->x */ 832 /* this is also used to reference automatic variables */ 833 834 q = &stab[p->in.right->tn.rval]; 835 p->in.right->in.op = FREE; 836 p->in.op = FREE; 837 p = pconvert( p->in.left ); 838 839 /* make p look like ptr to x */ 840 841 if( !ISPTR(p->in.type)){ 842 p->in.type = PTR+UNIONTY; 843 } 844 845 t = INCREF( q->stype ); 846 d = q->dimoff; 847 s = q->sizoff; 848 849 p = makety( p, t, d, s ); 850 851 /* compute the offset to be added */ 852 853 off = q->offset; 854 dsc = q->sclass; 855 856 if( dsc & FIELD ) { /* normalize offset */ 857 align = ALINT; 858 s = INT; 859 off = (off/align)*align; 860 } 861 if( off != 0 ) p = clocal( block( PLUS, p, offcon( off, t, d, s ), t, d, s ) ); 862 863 p = buildtree( UNARY MUL, p, NIL ); 864 865 /* if field, build field info */ 866 867 if( dsc & FIELD ){ 868 p = block( FLD, p, NIL, q->stype, 0, q->sizoff ); 869 p->tn.rval = PKFIELD( dsc&FLDSIZ, q->offset%align ); 870 } 871 872 return( clocal(p) ); 873 } 874 875 notlval(p) register NODE *p; { 876 877 /* return 0 if p an lvalue, 1 otherwise */ 878 879 again: 880 881 switch( p->in.op ){ 882 883 case FLD: 884 p = p->in.left; 885 goto again; 886 887 case UNARY MUL: 888 /* fix the &(a=b) bug, given that a and b are structures */ 889 if( p->in.left->in.op == STASG ) return( 1 ); 890 /* and the f().a bug, given that f returns a structure */ 891 if( p->in.left->in.op == UNARY STCALL || 892 p->in.left->in.op == STCALL ) return( 1 ); 893 case NAME: 894 case OREG: 895 if( ISARY(p->in.type) || ISFTN(p->in.type) ) return(1); 896 case REG: 897 return(0); 898 899 default: 900 return(1); 901 902 } 903 904 } 905 906 NODE * 907 bcon( i ){ /* make a constant node with value i */ 908 register NODE *p; 909 910 p = block( ICON, NIL, NIL, INT, 0, INT ); 911 p->tn.lval = i; 912 p->tn.rval = NONAME; 913 return( clocal(p) ); 914 } 915 916 NODE * 917 bpsize(p) register NODE *p; { 918 return( offcon( psize(p), p->in.type, p->fn.cdim, p->fn.csiz ) ); 919 } 920 921 OFFSZ 922 psize( p ) NODE *p; { 923 /* p is a node of type pointer; psize returns the 924 size of the thing pointed to */ 925 926 if( !ISPTR(p->in.type) ){ 927 uerror( "pointer required"); 928 return( SZINT ); 929 } 930 /* note: no pointers to fields */ 931 return( tsize( DECREF(p->in.type), p->fn.cdim, p->fn.csiz ) ); 932 } 933 934 NODE * 935 convert( p, f ) register NODE *p; { 936 /* convert an operand of p 937 f is either CVTL or CVTR 938 operand has type int, and is converted by the size of the other side 939 */ 940 941 register NODE *q, *r; 942 943 q = (f==CVTL)?p->in.left:p->in.right; 944 945 r = block( PMCONV, 946 q, bpsize(f==CVTL?p->in.right:p->in.left), INT, 0, INT ); 947 r = clocal(r); 948 if( f == CVTL ) 949 p->in.left = r; 950 else 951 p->in.right = r; 952 return(p); 953 954 } 955 956 #ifndef econvert 957 econvert( p ) register NODE *p; { 958 959 /* change enums to ints, or appropriate types */ 960 961 register TWORD ty; 962 963 if( (ty=BTYPE(p->in.type)) == ENUMTY || ty == MOETY ) { 964 if( dimtab[ p->fn.csiz ] == SZCHAR ) ty = CHAR; 965 else if( dimtab[ p->fn.csiz ] == SZINT ) ty = INT; 966 else if( dimtab[ p->fn.csiz ] == SZSHORT ) ty = SHORT; 967 else ty = LONG; 968 ty = ctype( ty ); 969 p->fn.csiz = ty; 970 MODTYPE(p->in.type,ty); 971 if( p->in.op == ICON && ty != LONG ) p->in.type = p->fn.csiz = INT; 972 } 973 } 974 #endif 975 976 NODE * 977 pconvert( p ) register NODE *p; { 978 979 /* if p should be changed into a pointer, do so */ 980 981 if( ISARY( p->in.type) ){ 982 p->in.type = DECREF( p->in.type ); 983 ++p->fn.cdim; 984 return( buildtree( UNARY AND, p, NIL ) ); 985 } 986 if( ISFTN( p->in.type) ) 987 return( buildtree( UNARY AND, p, NIL ) ); 988 989 return( p ); 990 } 991 992 NODE * 993 oconvert(p) register NODE *p; { 994 /* convert the result itself: used for pointer and unsigned */ 995 996 switch(p->in.op) { 997 998 case LE: 999 case LT: 1000 case GE: 1001 case GT: 1002 if( ISUNSIGNED(p->in.left->in.type) || ISUNSIGNED(p->in.right->in.type) ) p->in.op += (ULE-LE); 1003 case EQ: 1004 case NE: 1005 return( p ); 1006 1007 case MINUS: 1008 return( clocal( block( PVCONV, 1009 p, bpsize(p->in.left), INT, 0, INT ) ) ); 1010 } 1011 1012 cerror( "illegal oconvert: %d", p->in.op ); 1013 1014 return(p); 1015 } 1016 1017 NODE * 1018 ptmatch(p) register NODE *p; { 1019 1020 /* makes the operands of p agree; they are 1021 either pointers or integers, by this time */ 1022 /* with MINUS, the sizes must be the same */ 1023 /* with COLON, the types must be the same */ 1024 1025 TWORD t1, t2, t; 1026 int o, d2, d, s2, s; 1027 1028 o = p->in.op; 1029 t = t1 = p->in.left->in.type; 1030 t2 = p->in.right->in.type; 1031 d = p->in.left->fn.cdim; 1032 d2 = p->in.right->fn.cdim; 1033 s = p->in.left->fn.csiz; 1034 s2 = p->in.right->fn.csiz; 1035 1036 switch( o ){ 1037 1038 case ASSIGN: 1039 case RETURN: 1040 case CAST: 1041 { break; } 1042 1043 case MINUS: 1044 { if( psize(p->in.left) != psize(p->in.right) ){ 1045 uerror( "illegal pointer subtraction"); 1046 } 1047 break; 1048 } 1049 case COLON: 1050 { if( t1 != t2 ) uerror( "illegal types in :"); 1051 break; 1052 } 1053 default: /* must work harder: relationals or comparisons */ 1054 1055 if( !ISPTR(t1) ){ 1056 t = t2; 1057 d = d2; 1058 s = s2; 1059 break; 1060 } 1061 if( !ISPTR(t2) ){ 1062 break; 1063 } 1064 1065 /* both are pointers */ 1066 if( talign(t2,s2) < talign(t,s) ){ 1067 t = t2; 1068 s = s2; 1069 } 1070 break; 1071 } 1072 1073 p->in.left = makety( p->in.left, t, d, s ); 1074 p->in.right = makety( p->in.right, t, d, s ); 1075 if( o!=MINUS && !logop(o) ){ 1076 1077 p->in.type = t; 1078 p->fn.cdim = d; 1079 p->fn.csiz = s; 1080 } 1081 1082 return(clocal(p)); 1083 } 1084 1085 int tdebug = 0; 1086 1087 NODE * 1088 tymatch(p) register NODE *p; { 1089 1090 /* satisfy the types of various arithmetic binary ops */ 1091 1092 /* rules are: 1093 if assignment, type of LHS 1094 if any float or doubles, make double 1095 if any longs, make long 1096 otherwise, make int 1097 if either operand is unsigned, the result is... 1098 */ 1099 1100 register TWORD t1, t2, t, tu; 1101 register o, u; 1102 1103 o = p->in.op; 1104 1105 t1 = p->in.left->in.type; 1106 t2 = p->in.right->in.type; 1107 if( (t1==UNDEF || t2==UNDEF) && o!=CAST ) 1108 uerror("void type illegal in expression"); 1109 1110 u = 0; 1111 if( ISUNSIGNED(t1) ){ 1112 u = 1; 1113 t1 = DEUNSIGN(t1); 1114 } 1115 if( ISUNSIGNED(t2) ){ 1116 u = 1; 1117 t2 = DEUNSIGN(t2); 1118 } 1119 1120 if( ( t1 == CHAR || t1 == SHORT ) && o!= RETURN ) t1 = INT; 1121 if( t2 == CHAR || t2 == SHORT ) t2 = INT; 1122 1123 #ifdef SPRECC 1124 if( t1 == DOUBLE || t2 == DOUBLE ) 1125 t = DOUBLE; 1126 else if( t1 == FLOAT || t2 == FLOAT ) 1127 t = FLOAT; 1128 #else 1129 if (t1 == DOUBLE || t1 == FLOAT || t2 == DOUBLE || t2 == FLOAT) 1130 t = DOUBLE; 1131 #endif 1132 else if( t1==LONG || t2==LONG ) t = LONG; 1133 else t = INT; 1134 1135 if( o == ASSIGN || o == CAST || o == RETURN ){ 1136 tu = p->in.left->in.type; 1137 t = t1; 1138 } 1139 else { 1140 tu = (u && UNSIGNABLE(t))?ENUNSIGN(t):t; 1141 } 1142 1143 /* because expressions have values that are at least as wide 1144 as INT or UNSIGNED, the only conversions needed 1145 are those involving FLOAT/DOUBLE, and those 1146 from LONG to INT and ULONG to UNSIGNED */ 1147 1148 if( t != t1 && ! asgop(o) ) 1149 p->in.left = makety( p->in.left, tu, 0, (int)tu ); 1150 1151 if( t != t2 || o==CAST) 1152 if ( tu == ENUMTY ) {/* always asgop */ 1153 p->in.right = makety( p->in.right, INT, 0, INT ); 1154 p->in.right->in.type = tu; 1155 p->in.right->fn.cdim = p->in.left->fn.cdim; 1156 p->in.right->fn.csiz = p->in.left->fn.csiz; 1157 } 1158 else 1159 p->in.right = makety( p->in.right, tu, 0, (int)tu ); 1160 1161 if( asgop(o) ){ 1162 p->in.type = p->in.left->in.type; 1163 p->fn.cdim = p->in.left->fn.cdim; 1164 p->fn.csiz = p->in.left->fn.csiz; 1165 } 1166 else if( !logop(o) ){ 1167 p->in.type = tu; 1168 p->fn.cdim = 0; 1169 p->fn.csiz = t; 1170 } 1171 1172 # ifndef BUG1 1173 if( tdebug ) printf( "tymatch(%o): %o %s %o => %o\n",p,t1,opst[o],t2,tu ); 1174 # endif 1175 1176 return(p); 1177 } 1178 1179 NODE * 1180 makety( p, t, d, s ) register NODE *p; TWORD t; { 1181 /* make p into type t by inserting a conversion */ 1182 1183 if( p->in.type == ENUMTY && p->in.op == ICON ) econvert(p); 1184 if( t == p->in.type ){ 1185 p->fn.cdim = d; 1186 p->fn.csiz = s; 1187 return( p ); 1188 } 1189 1190 if( t & TMASK ){ 1191 /* non-simple type */ 1192 return( block( PCONV, p, NIL, t, d, s ) ); 1193 } 1194 1195 if( p->in.op == ICON ){ 1196 if (t == DOUBLE) { 1197 p->in.op = DCON; 1198 if (ISUNSIGNED(p->in.type)) 1199 p->dpn.dval = /* (unsigned CONSZ) */ p->tn.lval; 1200 else 1201 p->dpn.dval = p->tn.lval; 1202 p->in.type = p->fn.csiz = t; 1203 return (clocal(p)); 1204 } 1205 if (t == FLOAT) { 1206 p->in.op = FCON; 1207 if( ISUNSIGNED(p->in.type) ){ 1208 p->fpn.fval = /* (unsigned CONSZ) */ p->tn.lval; 1209 } 1210 else { 1211 p->fpn.fval = p->tn.lval; 1212 } 1213 1214 p->in.type = p->fn.csiz = t; 1215 return( clocal(p) ); 1216 } 1217 } 1218 else if (p->in.op == FCON && t == DOUBLE) { 1219 double db; 1220 1221 p->in.op = DCON; 1222 db = p->fpn.fval; 1223 p->dpn.dval = db; 1224 p->in.type = p->fn.csiz = t; 1225 return (clocal(p)); 1226 } else if (p->in.op == DCON && t == FLOAT) { 1227 float fl; 1228 1229 p->in.op = FCON; 1230 fl = p->dpn.dval; 1231 #ifdef notdef 1232 if (fl != p->dpn.dval) 1233 werror("float conversion loses precision"); 1234 #endif 1235 p->fpn.fval = fl; 1236 p->in.type = p->fn.csiz = t; 1237 return (clocal(p)); 1238 } 1239 1240 return( clocal( block( SCONV, p, NIL, t, d, s ) ) ); 1241 1242 } 1243 1244 NODE * 1245 block( o, l, r, t, d, s ) register NODE *l, *r; TWORD t; { 1246 1247 register NODE *p; 1248 1249 p = talloc(); 1250 p->in.op = o; 1251 p->in.left = l; 1252 p->in.right = r; 1253 p->in.type = t; 1254 p->fn.cdim = d; 1255 p->fn.csiz = s; 1256 return(p); 1257 } 1258 1259 icons(p) register NODE *p; { 1260 /* if p is an integer constant, return its value */ 1261 int val; 1262 1263 if( p->in.op != ICON ){ 1264 uerror( "constant expected"); 1265 val = 1; 1266 } 1267 else { 1268 val = p->tn.lval; 1269 if( val != p->tn.lval ) uerror( "constant too big for cross-compiler" ); 1270 } 1271 tfree( p ); 1272 return(val); 1273 } 1274 1275 /* the intent of this table is to examine the 1276 operators, and to check them for 1277 correctness. 1278 1279 The table is searched for the op and the 1280 modified type (where this is one of the 1281 types INT (includes char and short), LONG, 1282 DOUBLE (includes FLOAT), and POINTER 1283 1284 The default action is to make the node type integer 1285 1286 The actions taken include: 1287 PUN check for puns 1288 CVTL convert the left operand 1289 CVTR convert the right operand 1290 TYPL the type is determined by the left operand 1291 TYPR the type is determined by the right operand 1292 TYMATCH force type of left and right to match, by inserting conversions 1293 PTMATCH like TYMATCH, but for pointers 1294 LVAL left operand must be lval 1295 CVTO convert the op 1296 NCVT do not convert the operands 1297 OTHER handled by code 1298 NCVTR convert the left operand, not the right... 1299 1300 */ 1301 1302 # define MINT 01 /* integer */ 1303 # define MDBI 02 /* integer or double */ 1304 # define MSTR 04 /* structure */ 1305 # define MPTR 010 /* pointer */ 1306 # define MPTI 020 /* pointer or integer */ 1307 # define MENU 040 /* enumeration variable or member */ 1308 # define MVOID 0100000 /* void type */ 1309 1310 opact( p ) NODE *p; { 1311 1312 register mt12, mt1, mt2, o; 1313 1314 mt1 = mt2 = mt12 = 0; 1315 1316 switch( optype(o=p->in.op) ){ 1317 1318 case BITYPE: 1319 mt2 = moditype( p->in.right->in.type ); 1320 case UTYPE: 1321 mt1 = moditype( p->in.left->in.type ); 1322 break; 1323 1324 } 1325 1326 if( ((mt1 | mt2) & MVOID) && 1327 o != COMOP && 1328 !(o == CAST && (mt1 & MVOID)) ){ 1329 /* if lhs of RETURN is void, grammar will complain */ 1330 if( o != RETURN ) 1331 uerror( "value of void expression used" ); 1332 return( NCVT ); 1333 } 1334 mt1 &= ~MVOID; 1335 mt2 &= ~MVOID; 1336 mt12 = mt1 & mt2; 1337 1338 switch( o ){ 1339 1340 case NAME : 1341 case STRING : 1342 case ICON : 1343 case FCON : 1344 case DCON : 1345 case CALL : 1346 case UNARY CALL: 1347 case UNARY MUL: 1348 { return( OTHER ); } 1349 case UNARY MINUS: 1350 if( mt1 & MDBI ) return( TYPL ); 1351 break; 1352 1353 case COMPL: 1354 if( mt1 & MINT ) return( TYPL ); 1355 break; 1356 1357 case UNARY AND: 1358 { return( NCVT+OTHER ); } 1359 case INIT: 1360 case CM: 1361 return( 0 ); 1362 1363 case NOT: 1364 case CBRANCH: 1365 if( mt1 & MSTR ) break; 1366 return( 0 ); 1367 1368 case ANDAND: 1369 case OROR: 1370 if( (mt1 & MSTR) || (mt2 & MSTR) ) break; 1371 return( 0 ); 1372 1373 case MUL: 1374 case DIV: 1375 if( mt12 & MDBI ) return( TYMATCH ); 1376 break; 1377 1378 case MOD: 1379 case AND: 1380 case OR: 1381 case ER: 1382 if( mt12 & MINT ) return( TYMATCH ); 1383 break; 1384 1385 case LS: 1386 case RS: 1387 if( mt12 & MINT ) return( TYMATCH+OTHER ); 1388 break; 1389 1390 case EQ: 1391 case NE: 1392 case LT: 1393 case LE: 1394 case GT: 1395 case GE: 1396 if( (mt1&MENU)||(mt2&MENU) ) return( PTMATCH+PUN+NCVT ); 1397 if( mt12 & MDBI ) return( TYMATCH+CVTO ); 1398 else if( mt12 & MPTR ) return( PTMATCH+PUN ); 1399 else if( mt12 & MPTI ) return( PTMATCH+PUN ); 1400 else break; 1401 1402 case QUEST: 1403 case COMOP: 1404 if( mt2&MENU ) return( TYPR+NCVTR ); 1405 return( TYPR ); 1406 1407 case STREF: 1408 return( NCVTR+OTHER ); 1409 1410 case FORCE: 1411 return( TYPL ); 1412 1413 case COLON: 1414 if( mt12 & MENU ) return( NCVT+PUN+PTMATCH ); 1415 else if( mt12 & MDBI ) return( TYMATCH ); 1416 else if( mt12 & MPTR ) return( TYPL+PTMATCH+PUN ); 1417 else if( (mt1&MINT) && (mt2&MPTR) ) return( TYPR+PUN ); 1418 else if( (mt1&MPTR) && (mt2&MINT) ) return( TYPL+PUN ); 1419 else if( mt12 & MSTR ) return( NCVT+TYPL+OTHER ); 1420 break; 1421 1422 case ASSIGN: 1423 case RETURN: 1424 if( mt12 & MSTR ) return( LVAL+NCVT+TYPL+OTHER ); 1425 else if( (mt1&MENU)||(mt2&MENU) ) return( LVAL+NCVT+TYPL+PTMATCH+PUN ); 1426 case CAST: 1427 if(o==CAST && mt1==0)return(TYPL+TYMATCH); 1428 else if( mt12 & MDBI ) return( TYPL+LVAL+TYMATCH ); 1429 else if( mt2 == 0 && 1430 ( p->in.right->in.op == CALL || 1431 p->in.right->in.op == UNARY CALL)) break; 1432 else if( mt1 & MPTR ) return( LVAL+PTMATCH+PUN ); 1433 else if( mt12 & MPTI ) return( TYPL+LVAL+TYMATCH+PUN ); 1434 break; 1435 1436 case ASG LS: 1437 case ASG RS: 1438 if( mt12 & MINT ) return( TYPL+LVAL+OTHER ); 1439 break; 1440 1441 case ASG MUL: 1442 case ASG DIV: 1443 if( mt12 & MDBI ) return( LVAL+TYMATCH ); 1444 break; 1445 1446 case ASG MOD: 1447 case ASG AND: 1448 case ASG OR: 1449 case ASG ER: 1450 if( mt12 & MINT ) return( LVAL+TYMATCH ); 1451 break; 1452 1453 case ASG PLUS: 1454 case ASG MINUS: 1455 case INCR: 1456 case DECR: 1457 if( mt12 & MDBI ) return( TYMATCH+LVAL ); 1458 else if( (mt1&MPTR) && (mt2&MINT) ) return( TYPL+LVAL+CVTR ); 1459 break; 1460 1461 case MINUS: 1462 if( mt12 & MPTR ) return( CVTO+PTMATCH+PUN ); 1463 if( mt2 & MPTR ) break; 1464 case PLUS: 1465 if( mt12 & MDBI ) return( TYMATCH ); 1466 else if( (mt1&MPTR) && (mt2&MINT) ) return( TYPL+CVTR ); 1467 else if( (mt1&MINT) && (mt2&MPTR) ) return( TYPR+CVTL ); 1468 1469 } 1470 if( mt12 == MSTR ) 1471 uerror( "%s is not a permitted struct/union operation", opst[o] ); 1472 else 1473 uerror( "operands of %s have incompatible types", opst[o] ); 1474 return( NCVT ); 1475 } 1476 1477 moditype( ty ) TWORD ty; { 1478 1479 switch( ty ){ 1480 1481 case TVOID: 1482 return( MPTR ); 1483 case UNDEF: 1484 return( MVOID ); 1485 case ENUMTY: 1486 case MOETY: 1487 return( MENU|MINT|MDBI|MPTI ); /* enums are ints */ 1488 1489 case STRTY: 1490 case UNIONTY: 1491 return( MSTR ); 1492 1493 case CHAR: 1494 case SHORT: 1495 case UCHAR: 1496 case USHORT: 1497 return( MINT|MPTI|MDBI ); 1498 case UNSIGNED: 1499 case ULONG: 1500 case INT: 1501 case LONG: 1502 return( MINT|MDBI|MPTI ); 1503 case FLOAT: 1504 case DOUBLE: 1505 return( MDBI ); 1506 default: 1507 return( MPTR|MPTI ); 1508 1509 } 1510 } 1511 1512 NODE * 1513 doszof( p ) register NODE *p; { 1514 /* do sizeof p */ 1515 int i; 1516 1517 /* whatever is the meaning of this if it is a bitfield? */ 1518 i = tsize( p->in.type, p->fn.cdim, p->fn.csiz )/SZCHAR; 1519 1520 tfree(p); 1521 if( i <= 0 ) werror( "sizeof returns 0" ); 1522 return( bcon( i ) ); 1523 } 1524 1525 # ifndef BUG2 1526 eprint( p, down, a, b ) register NODE *p; int *a, *b; { 1527 register ty; 1528 1529 *a = *b = down+1; 1530 while( down > 1 ){ 1531 printf( "\t" ); 1532 down -= 2; 1533 } 1534 if( down ) printf( " " ); 1535 1536 ty = optype( p->in.op ); 1537 1538 printf("%o) %s, ", p, opst[p->in.op] ); 1539 if( ty == LTYPE ){ 1540 printf( CONFMT, p->tn.lval ); 1541 printf( ", %d, ", p->tn.rval ); 1542 } 1543 tprint( p->in.type ); 1544 printf( ", %d, %d\n", p->fn.cdim, p->fn.csiz ); 1545 } 1546 # endif 1547 1548 prtdcon( p ) register NODE *p; { 1549 int o = p->in.op, i; 1550 1551 if( o == DCON || o == FCON ){ 1552 locctr( DATA ); 1553 defalign( o == DCON ? ALDOUBLE : ALFLOAT ); 1554 deflab( i = getlab() ); 1555 if( o == FCON ) 1556 fincode( p->fpn.fval, SZFLOAT ); 1557 else 1558 fincode( p->dpn.dval, SZDOUBLE ); 1559 p->tn.lval = 0; 1560 p->tn.rval = -i; 1561 p->in.type = (o == DCON ? DOUBLE : FLOAT); 1562 p->in.op = NAME; 1563 } 1564 } 1565 1566 1567 int edebug = 0; 1568 ecomp( p ) register NODE *p; { 1569 # ifndef BUG2 1570 if( edebug ) fwalk( p, eprint, 0 ); 1571 # endif 1572 if( !reached ){ 1573 werror( "statement not reached" ); 1574 reached = 1; 1575 } 1576 p = optim(p); 1577 walkf( p, prtdcon ); 1578 locctr( PROG ); 1579 ecode( p ); 1580 tfree(p); 1581 } 1582 1583 # ifdef STDPRTREE 1584 # ifndef ONEPASS 1585 1586 prtree(p) register NODE *p; { 1587 1588 register struct symtab *q; 1589 register ty; 1590 1591 # ifdef MYPRTREE 1592 MYPRTREE(p); /* local action can be taken here; then return... */ 1593 #endif 1594 1595 ty = optype(p->in.op); 1596 1597 printf( "%d\t", p->in.op ); 1598 1599 if( ty == LTYPE ) { 1600 printf( CONFMT, p->tn.lval ); 1601 printf( "\t" ); 1602 } 1603 if( ty != BITYPE ) { 1604 if( p->in.op == NAME || p->in.op == ICON ) printf( "0\t" ); 1605 else printf( "%d\t", p->tn.rval ); 1606 } 1607 1608 printf( "%o\t", p->in.type ); 1609 1610 /* handle special cases */ 1611 1612 switch( p->in.op ){ 1613 1614 case NAME: 1615 case ICON: 1616 /* print external name */ 1617 if( p->tn.rval == NONAME ) printf( "\n" ); 1618 else if( p->tn.rval >= 0 ){ 1619 q = &stab[p->tn.rval]; 1620 printf( "%s\n", exname(q->sname) ); 1621 } 1622 else { /* label */ 1623 printf( LABFMT, -p->tn.rval ); 1624 } 1625 break; 1626 1627 case STARG: 1628 case STASG: 1629 case STCALL: 1630 case UNARY STCALL: 1631 /* print out size */ 1632 /* use lhs size, in order to avoid hassles with the structure `.' operator */ 1633 1634 /* note: p->in.left not a field... */ 1635 printf( CONFMT, (CONSZ) tsize( STRTY, p->in.left->fn.cdim, p->in.left->fn.csiz ) ); 1636 printf( "\t%d\t\n", talign( STRTY, p->in.left->fn.csiz ) ); 1637 break; 1638 1639 default: 1640 printf( "\n" ); 1641 } 1642 1643 if( ty != LTYPE ) prtree( p->in.left ); 1644 if( ty == BITYPE ) prtree( p->in.right ); 1645 1646 } 1647 1648 # else 1649 1650 p2tree(p) register NODE *p; { 1651 register ty; 1652 1653 # ifdef MYP2TREE 1654 MYP2TREE(p); /* local action can be taken here; then return... */ 1655 # endif 1656 1657 ty = optype(p->in.op); 1658 1659 switch( p->in.op ){ 1660 1661 case NAME: 1662 case ICON: 1663 #ifndef FLEXNAMES 1664 if( p->tn.rval == NONAME ) p->in.name[0] = '\0'; 1665 #else 1666 if( p->tn.rval == NONAME ) p->in.name = ""; 1667 #endif 1668 else if( p->tn.rval >= 0 ){ /* copy name from exname */ 1669 register char *cp; 1670 register i; 1671 cp = exname( stab[p->tn.rval].sname ); 1672 #ifndef FLEXNAMES 1673 for( i=0; i<NCHNAM; ++i ) p->in.name[i] = *cp++; 1674 #else 1675 p->in.name = tstr(cp); 1676 #endif 1677 } 1678 #ifndef FLEXNAMES 1679 else sprintf( p->in.name, LABFMT, -p->tn.rval ); 1680 #else 1681 else { 1682 char temp[32]; 1683 sprintf( temp, LABFMT, -p->tn.rval ); 1684 p->in.name = tstr(temp); 1685 } 1686 #endif 1687 break; 1688 1689 case STARG: 1690 case STASG: 1691 case STCALL: 1692 case UNARY STCALL: 1693 /* set up size parameters */ 1694 p->stn.stsize = (tsize(STRTY,p->in.left->fn.cdim,p->in.left->fn.csiz)+SZCHAR-1)/SZCHAR; 1695 p->stn.stalign = talign(STRTY,p->in.left->fn.csiz)/SZCHAR; 1696 break; 1697 1698 case REG: 1699 rbusy( p->tn.rval, p->in.type ); 1700 default: 1701 #ifndef FLEXNAMES 1702 p->in.name[0] = '\0'; 1703 #else 1704 p->in.name = ""; 1705 #endif 1706 } 1707 1708 p->in.rall = NOPREF; 1709 1710 if( ty != LTYPE ) p2tree( p->in.left ); 1711 if( ty == BITYPE ) p2tree( p->in.right ); 1712 } 1713 1714 # endif 1715 # endif 1716