1 #ifndef lint 2 static char *sccsid ="@(#)trees.c 4.31 (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 if( o == ASSIGN || o == CAST || o == RETURN ) 1153 { 1154 tu = p->in.left->in.type; 1155 t = t1; 1156 } 1157 else { 1158 tu = (u && UNSIGNABLE(t))?ENUNSIGN(t):t; 1159 } 1160 1161 /* because expressions have values that are at least as wide 1162 as INT or UNSIGNED, the only conversions needed 1163 are those involving FLOAT/DOUBLE, and those 1164 from LONG to INT and ULONG to UNSIGNED */ 1165 1166 if( t != t1 && ! asgop(o) ) 1167 p->in.left = makety( p->in.left, tu, 0, (int)tu ); 1168 1169 if( t != t2 || o==CAST) 1170 if ( tu == ENUMTY ) {/* always asgop */ 1171 p->in.right = makety( p->in.right, INT, 0, INT ); 1172 p->in.right->in.type = tu; 1173 p->in.right->fn.cdim = p->in.left->fn.cdim; 1174 p->in.right->fn.csiz = p->in.left->fn.csiz; 1175 } 1176 else 1177 p->in.right = makety( p->in.right, tu, 0, (int)tu ); 1178 1179 if( asgop(o) ){ 1180 p->in.type = p->in.left->in.type; 1181 p->fn.cdim = p->in.left->fn.cdim; 1182 p->fn.csiz = p->in.left->fn.csiz; 1183 } 1184 else if( !logop(o) ){ 1185 p->in.type = tu; 1186 p->fn.cdim = 0; 1187 p->fn.csiz = t; 1188 } 1189 1190 # ifndef BUG1 1191 if( tdebug ) printf( "tymatch(%o): %o %s %o => %o\n",p,t1,opst[o],t2,tu ); 1192 # endif 1193 1194 return(p); 1195 } 1196 1197 NODE * 1198 makety( p, t, d, s ) register NODE *p; TWORD t; { 1199 /* make p into type t by inserting a conversion */ 1200 1201 if( p->in.type == ENUMTY && p->in.op == ICON ) econvert(p); 1202 if( t == p->in.type ){ 1203 p->fn.cdim = d; 1204 p->fn.csiz = s; 1205 return( p ); 1206 } 1207 1208 if( t & TMASK ){ 1209 /* non-simple type */ 1210 return( block( PCONV, p, NIL, t, d, s ) ); 1211 } 1212 1213 if( p->in.op == ICON ){ 1214 if (t == DOUBLE) { 1215 p->in.op = DCON; 1216 if (ISUNSIGNED(p->in.type)) 1217 p->dpn.dval = (unsigned CONSZ) p->tn.lval; 1218 else 1219 p->dpn.dval = p->tn.lval; 1220 p->in.type = p->fn.csiz = t; 1221 return (clocal(p)); 1222 } 1223 if (t == FLOAT) { 1224 p->in.op = FCON; 1225 if( ISUNSIGNED(p->in.type) ){ 1226 p->fpn.fval = (unsigned CONSZ) p->tn.lval; 1227 } 1228 else { 1229 p->fpn.fval = p->tn.lval; 1230 } 1231 1232 p->in.type = p->fn.csiz = t; 1233 return( clocal(p) ); 1234 } 1235 } 1236 else if (p->in.op == FCON && t == DOUBLE) { 1237 double db; 1238 1239 p->in.op = DCON; 1240 db = p->fpn.fval; 1241 p->dpn.dval = db; 1242 p->in.type = p->fn.csiz = t; 1243 return (clocal(p)); 1244 } else if (p->in.op == DCON && t == FLOAT) { 1245 float fl; 1246 1247 p->in.op = FCON; 1248 fl = p->dpn.dval; 1249 #ifdef notdef 1250 if (fl != p->dpn.dval) 1251 werror("float conversion loses precision"); 1252 #endif 1253 p->fpn.fval = fl; 1254 p->in.type = p->fn.csiz = t; 1255 return (clocal(p)); 1256 } 1257 1258 return( clocal( block( SCONV, p, NIL, t, d, s ) ) ); 1259 1260 } 1261 1262 NODE * 1263 block( o, l, r, t, d, s ) register NODE *l, *r; TWORD t; { 1264 1265 register NODE *p; 1266 1267 p = talloc(); 1268 p->in.op = o; 1269 p->in.left = l; 1270 p->in.right = r; 1271 p->in.type = t; 1272 p->fn.cdim = d; 1273 p->fn.csiz = s; 1274 return(p); 1275 } 1276 1277 icons(p) register NODE *p; { 1278 /* if p is an integer constant, return its value */ 1279 int val; 1280 1281 if( p->in.op != ICON ){ 1282 uerror( "constant expected"); 1283 val = 1; 1284 } 1285 else { 1286 val = p->tn.lval; 1287 if( val != p->tn.lval ) uerror( "constant too big for cross-compiler" ); 1288 } 1289 tfree( p ); 1290 return(val); 1291 } 1292 1293 /* the intent of this table is to examine the 1294 operators, and to check them for 1295 correctness. 1296 1297 The table is searched for the op and the 1298 modified type (where this is one of the 1299 types INT (includes char and short), LONG, 1300 DOUBLE (includes FLOAT), and POINTER 1301 1302 The default action is to make the node type integer 1303 1304 The actions taken include: 1305 PUN check for puns 1306 CVTL convert the left operand 1307 CVTR convert the right operand 1308 TYPL the type is determined by the left operand 1309 TYPR the type is determined by the right operand 1310 TYMATCH force type of left and right to match, by inserting conversions 1311 PTMATCH like TYMATCH, but for pointers 1312 LVAL left operand must be lval 1313 CVTO convert the op 1314 NCVT do not convert the operands 1315 OTHER handled by code 1316 NCVTR convert the left operand, not the right... 1317 1318 */ 1319 1320 # define MINT 01 /* integer */ 1321 # define MDBI 02 /* integer or double */ 1322 # define MSTR 04 /* structure */ 1323 # define MPTR 010 /* pointer */ 1324 # define MPTI 020 /* pointer or integer */ 1325 # define MENU 040 /* enumeration variable or member */ 1326 # define MVOID 0100000 /* void type */ 1327 1328 opact( p ) NODE *p; { 1329 1330 register mt12, mt1, mt2, o; 1331 1332 mt1 = mt2 = mt12 = 0; 1333 1334 switch( optype(o=p->in.op) ){ 1335 1336 case BITYPE: 1337 mt2 = moditype( p->in.right->in.type ); 1338 case UTYPE: 1339 mt1 = moditype( p->in.left->in.type ); 1340 break; 1341 1342 } 1343 1344 if( ((mt1 | mt2) & MVOID) && 1345 o != COMOP && 1346 o != COLON && 1347 !(o == QUEST && (mt1 & MVOID) == 0) && 1348 !(o == CAST && (mt1 & MVOID)) ){ 1349 /* if lhs of RETURN is void, grammar will complain */ 1350 if( o != RETURN ) 1351 uerror( "value of void expression used" ); 1352 return( NCVT ); 1353 } 1354 mt12 = mt1 & mt2; 1355 1356 switch( o ){ 1357 1358 case NAME : 1359 case STRING : 1360 case ICON : 1361 case FCON : 1362 case DCON : 1363 case CALL : 1364 case UNARY CALL: 1365 case UNARY MUL: 1366 { return( OTHER ); } 1367 case UNARY MINUS: 1368 if( mt1 & MENU ) return( 0 ); 1369 if( mt1 & MDBI ) return( TYPL ); 1370 break; 1371 1372 case COMPL: 1373 if( mt1 & MENU ) return( 0 ); 1374 if( mt1 & MINT ) return( TYPL ); 1375 break; 1376 1377 case UNARY AND: 1378 { return( NCVT+OTHER ); } 1379 case INIT: 1380 case CM: 1381 return( 0 ); 1382 1383 case NOT: 1384 case CBRANCH: 1385 if( mt1 & MSTR ) break; 1386 return( 0 ); 1387 1388 case ANDAND: 1389 case OROR: 1390 if( (mt1 & MSTR) || (mt2 & MSTR) ) break; 1391 return( 0 ); 1392 1393 case MUL: 1394 case DIV: 1395 if( mt12 & MDBI ) return( TYMATCH ); 1396 break; 1397 1398 case MOD: 1399 case AND: 1400 case OR: 1401 case ER: 1402 if( mt12 & MINT ) return( TYMATCH ); 1403 break; 1404 1405 case LS: 1406 case RS: 1407 if( mt12 & MINT ) return( TYMATCH+OTHER ); 1408 break; 1409 1410 case EQ: 1411 case NE: 1412 case LT: 1413 case LE: 1414 case GT: 1415 case GE: 1416 if( mt12 & MENU ) return( TYMATCH+NCVT+PUN ); 1417 if( mt12 & MDBI ) return( TYMATCH+NCVT+CVTO ); 1418 else if( mt12 & MPTR ) return( PTMATCH+PUN ); 1419 else if( mt12 & MPTI ) return( PTMATCH+PUN ); 1420 else break; 1421 1422 case QUEST: 1423 case COMOP: 1424 if( mt2&MENU ) return( TYPR+NCVTR ); 1425 return( TYPR ); 1426 1427 case STREF: 1428 return( NCVTR+OTHER ); 1429 1430 case FORCE: 1431 return( TYPL ); 1432 1433 case COLON: 1434 if( mt12 & MENU ) return( NCVT+PUN+TYMATCH ); 1435 else if( mt12 & MDBI ) return( NCVT+TYMATCH ); 1436 else if( mt12 & MPTR ) return( TYPL+PTMATCH+PUN ); 1437 else if( (mt1&MINT) && (mt2&MPTR) ) return( TYPR+PUN ); 1438 else if( (mt1&MPTR) && (mt2&MINT) ) return( TYPL+PUN ); 1439 else if( mt12 & MSTR ) return( NCVT+TYPL+OTHER ); 1440 else if( mt12 == MVOID ) return( NCVT+TYPL ); 1441 break; 1442 1443 case ASSIGN: 1444 case RETURN: 1445 if( mt12 & MSTR ) return( LVAL+NCVT+TYPL+OTHER ); 1446 else if( mt12 & MENU ) return( LVAL+NCVT+TYPL+TYMATCH+PUN ); 1447 case CAST: 1448 if(o==CAST && mt1==MVOID)return(TYPL+TYMATCH); 1449 else if( mt12 & MDBI ) return( TYPL+LVAL+NCVT+TYMATCH ); 1450 else if( mt2 == MVOID && 1451 ( p->in.right->in.op == CALL || 1452 p->in.right->in.op == UNARY CALL)) break; 1453 else if( (mt1 & MPTR) && (mt2 & MPTI) ) 1454 return( LVAL+PTMATCH+PUN ); 1455 else if( mt12 & MPTI ) return( TYPL+LVAL+TYMATCH+PUN ); 1456 break; 1457 1458 case ASG LS: 1459 case ASG RS: 1460 if( mt12 & MINT ) return( TYPL+LVAL+OTHER ); 1461 break; 1462 1463 case ASG MUL: 1464 case ASG DIV: 1465 if( mt12 & MDBI ) return( LVAL+TYMATCH ); 1466 break; 1467 1468 case ASG MOD: 1469 case ASG AND: 1470 case ASG OR: 1471 case ASG ER: 1472 if( mt12 & MINT ) return( LVAL+TYMATCH ); 1473 break; 1474 1475 case ASG PLUS: 1476 case ASG MINUS: 1477 case INCR: 1478 case DECR: 1479 if( mt12 & MDBI ) return( TYMATCH+LVAL ); 1480 else if( (mt1&MPTR) && (mt2&MINT) ) return( TYPL+LVAL+CVTR ); 1481 break; 1482 1483 case MINUS: 1484 if( mt12 & MPTR ) return( CVTO+PTMATCH+PUN ); 1485 if( mt2 & MPTR ) break; 1486 case PLUS: 1487 if( mt12 & MDBI ) return( TYMATCH ); 1488 else if( (mt1&MPTR) && (mt2&MINT) ) return( TYPL+CVTR ); 1489 else if( (mt1&MINT) && (mt2&MPTR) ) return( TYPR+CVTL ); 1490 1491 } 1492 if( mt12 == MSTR ) 1493 uerror( "%s is not a permitted struct/union operation", opst[o] ); 1494 else 1495 uerror( "operands of %s have incompatible types", opst[o] ); 1496 return( NCVT ); 1497 } 1498 1499 moditype( ty ) TWORD ty; { 1500 1501 switch( ty ){ 1502 1503 case UNDEF: 1504 return( MVOID ); 1505 case ENUMTY: 1506 case MOETY: 1507 return( MENU|MINT|MDBI|MPTI ); /* enums are ints */ 1508 1509 case STRTY: 1510 case UNIONTY: 1511 return( MSTR ); 1512 1513 case CHAR: 1514 case SHORT: 1515 case UCHAR: 1516 case USHORT: 1517 return( MINT|MPTI|MDBI ); 1518 case UNSIGNED: 1519 case ULONG: 1520 case INT: 1521 case LONG: 1522 return( MINT|MDBI|MPTI ); 1523 case FLOAT: 1524 case DOUBLE: 1525 return( MDBI ); 1526 default: 1527 return( MPTR|MPTI ); 1528 1529 } 1530 } 1531 1532 NODE * 1533 doszof( p ) register NODE *p; { 1534 /* do sizeof p */ 1535 int i; 1536 1537 /* whatever is the meaning of this if it is a bitfield? */ 1538 i = tsize( p->in.type, p->fn.cdim, p->fn.csiz )/SZCHAR; 1539 1540 tfree(p); 1541 if( i <= 0 ) werror( "sizeof returns 0" ); 1542 return( bcon( i ) ); 1543 } 1544 1545 # ifndef BUG2 1546 eprint( p, down, a, b ) register NODE *p; int *a, *b; { 1547 register ty; 1548 1549 *a = *b = down+1; 1550 while( down > 1 ){ 1551 printf( "\t" ); 1552 down -= 2; 1553 } 1554 if( down ) printf( " " ); 1555 1556 ty = optype( p->in.op ); 1557 1558 printf("%o) %s, ", p, opst[p->in.op] ); 1559 if( ty == LTYPE ){ 1560 printf( CONFMT, p->tn.lval ); 1561 printf( ", %d, ", p->tn.rval ); 1562 } 1563 tprint( p->in.type ); 1564 printf( ", %d, %d\n", p->fn.cdim, p->fn.csiz ); 1565 } 1566 # endif 1567 1568 #ifndef PRTDCON 1569 prtdcon( p ) register NODE *p; { 1570 int o = p->in.op, i; 1571 1572 if( o == DCON || o == FCON ){ 1573 (void) locctr( DATA ); 1574 defalign( o == DCON ? ALDOUBLE : ALFLOAT ); 1575 deflab( i = getlab() ); 1576 if( o == FCON ) 1577 fincode( p->fpn.fval, SZFLOAT ); 1578 else 1579 fincode( p->dpn.dval, SZDOUBLE ); 1580 p->tn.lval = 0; 1581 p->tn.rval = -i; 1582 p->in.type = (o == DCON ? DOUBLE : FLOAT); 1583 p->in.op = NAME; 1584 } 1585 } 1586 #endif PRTDCON 1587 1588 1589 int edebug = 0; 1590 ecomp( p ) register NODE *p; { 1591 # ifndef BUG2 1592 if( edebug ) fwalk( p, eprint, 0 ); 1593 # endif 1594 if( !reached ){ 1595 werror( "statement not reached" ); 1596 reached = 1; 1597 } 1598 p = optim(p); 1599 walkf( p, prtdcon ); 1600 (void) locctr( PROG ); 1601 ecode( p ); 1602 tfree(p); 1603 } 1604 1605 # ifdef STDPRTREE 1606 # ifndef ONEPASS 1607 1608 prtree(p) register NODE *p; { 1609 1610 register struct symtab *q; 1611 register ty; 1612 1613 # ifdef MYPRTREE 1614 MYPRTREE(p); /* local action can be taken here; then return... */ 1615 #endif 1616 1617 ty = optype(p->in.op); 1618 1619 printf( "%d\t", p->in.op ); 1620 1621 if( ty == LTYPE ) { 1622 printf( CONFMT, p->tn.lval ); 1623 printf( "\t" ); 1624 } 1625 if( ty != BITYPE ) { 1626 if( p->in.op == NAME || p->in.op == ICON ) printf( "0\t" ); 1627 else printf( "%d\t", p->tn.rval ); 1628 } 1629 1630 printf( "%o\t", p->in.type ); 1631 1632 /* handle special cases */ 1633 1634 switch( p->in.op ){ 1635 1636 case NAME: 1637 case ICON: 1638 /* print external name */ 1639 if( p->tn.rval == NONAME ) printf( "\n" ); 1640 else if( p->tn.rval >= 0 ){ 1641 q = &stab[p->tn.rval]; 1642 printf( "%s\n", exname(q->sname) ); 1643 } 1644 else { /* label */ 1645 printf( LABFMT, -p->tn.rval ); 1646 } 1647 break; 1648 1649 case STARG: 1650 case STASG: 1651 case STCALL: 1652 case UNARY STCALL: 1653 /* print out size */ 1654 /* use lhs size, in order to avoid hassles with the structure `.' operator */ 1655 1656 /* note: p->in.left not a field... */ 1657 printf( CONFMT, (CONSZ) tsize( STRTY, p->in.left->fn.cdim, p->in.left->fn.csiz ) ); 1658 printf( "\t%d\t\n", talign( STRTY, p->in.left->fn.csiz ) ); 1659 break; 1660 1661 default: 1662 printf( "\n" ); 1663 } 1664 1665 if( ty != LTYPE ) prtree( p->in.left ); 1666 if( ty == BITYPE ) prtree( p->in.right ); 1667 1668 } 1669 1670 # else 1671 1672 p2tree(p) register NODE *p; { 1673 register ty; 1674 1675 # ifdef MYP2TREE 1676 MYP2TREE(p); /* local action can be taken here; then return... */ 1677 # endif 1678 1679 ty = optype(p->in.op); 1680 1681 switch( p->in.op ){ 1682 1683 case NAME: 1684 case ICON: 1685 #ifndef FLEXNAMES 1686 if( p->tn.rval == NONAME ) p->in.name[0] = '\0'; 1687 #else 1688 if( p->tn.rval == NONAME ) p->in.name = ""; 1689 #endif 1690 else if( p->tn.rval >= 0 ){ /* copy name from exname */ 1691 register char *cp; 1692 cp = exname( stab[p->tn.rval].sname ); 1693 #ifndef FLEXNAMES 1694 { 1695 register i; 1696 for( i=0; i<NCHNAM; ++i ) 1697 p->in.name[i] = *cp++; 1698 } 1699 #else 1700 p->in.name = tstr(cp); 1701 #endif 1702 } 1703 #ifndef FLEXNAMES 1704 else sprintf( p->in.name, LABFMT, -p->tn.rval ); 1705 #else 1706 else { 1707 char temp[32]; 1708 sprintf( temp, LABFMT, -p->tn.rval ); 1709 p->in.name = tstr(temp); 1710 } 1711 #endif 1712 break; 1713 1714 case STARG: 1715 case STASG: 1716 case STCALL: 1717 case UNARY STCALL: 1718 /* set up size parameters */ 1719 p->stn.stsize = (tsize(STRTY,p->in.left->fn.cdim,p->in.left->fn.csiz)+SZCHAR-1)/SZCHAR; 1720 p->stn.stalign = talign(STRTY,p->in.left->fn.csiz)/SZCHAR; 1721 break; 1722 1723 case REG: 1724 rbusy( p->tn.rval, p->in.type ); 1725 default: 1726 #ifndef FLEXNAMES 1727 p->in.name[0] = '\0'; 1728 #else 1729 p->in.name = ""; 1730 #endif 1731 } 1732 1733 p->in.rall = NOPREF; 1734 1735 if( ty != LTYPE ) p2tree( p->in.left ); 1736 if( ty == BITYPE ) p2tree( p->in.right ); 1737 } 1738 1739 # endif 1740 # endif 1741