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