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