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