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