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