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