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