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