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