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