|
|
1.1 ! root 1: /* @(#) cgen.c: 1.2 1/12/84 */ ! 2: ! 3: # include "mfile2.h" ! 4: # define istnode(p) (p->in.op==REG && istreg(p->tn.rval)) ! 5: ! 6: /* ! 7: ** For God's workes are, like him, all infinite ! 8: ** And curious search but craftie sin's delight. ! 9: */ ! 10: ! 11: rewcom( p, goal ) ! 12: NODE *p; ! 13: ! 14: { ! 15: /* find all , ops, move as high as is legal */ ! 16: /* rewrite p in place; this takes some doing! */ ! 17: /* while we are at it, take care of setting the goal field */ ! 18: int o, ty, g1, g2; ! 19: NODE *l, *r, *ql, *qr; ! 20: ! 21: o = p->tn.op; ! 22: g1 = g2 = NRGS; ! 23: p->tn.goal = goal; ! 24: ! 25: /* special cases for subtrees: ! 26: ** GENBR has left as Condition codes ! 27: ** COMOP has left as Effects ! 28: ** COLON, GENUBR, CM, GENLAB have descendents = node ! 29: ** CALL, STCALL, FORTCALL has right as Effects ! 30: ** All others use registers ! 31: */ ! 32: ! 33: switch( o ) ! 34: { ! 35: ! 36: case FREE: ! 37: cerror( "rewcom(%d) is FREE", p-node ); ! 38: ! 39: case GENBR: ! 40: g1 = CCC; ! 41: break; ! 42: ! 43: case COMOP: ! 44: g1 = CEFF; ! 45: g2 = goal; ! 46: break; ! 47: ! 48: case COLON: ! 49: case GENUBR: ! 50: case CM: ! 51: case GENLAB: ! 52: g1 = g2 = goal; ! 53: break; ! 54: ! 55: case CALL: ! 56: case STCALL: ! 57: case FORTCALL: ! 58: g2 = CEFF; ! 59: break; ! 60: } ! 61: ! 62: ! 63: switch( ty = optype(o) ) ! 64: { ! 65: ! 66: case BITYPE: ! 67: rewcom( r = p->in.right, g2 ); ! 68: case UTYPE: ! 69: rewcom( l = p->in.left, g1 ); ! 70: break; ! 71: case LTYPE: ! 72: return; ! 73: } ! 74: ! 75: if( o==COMOP || o==COLON || o==GENLAB ) return; ! 76: ! 77: /* look for (A,B) op C and A op (B,C), and rewrite */ ! 78: /* A,B if A headed by GENBR can't be rewritten */ ! 79: /* the assumption is that B is executed immediately after A, */ ! 80: /* and this won't necessarily be true if op is commutative */ ! 81: ! 82: if( l->tn.op == COMOP && l->in.left->tn.op != GENBR ) ! 83: { ! 84: /* rewrite it... */ ! 85: /* (A,B) op C => A,(B op C) */ ! 86: /* also, for unary ops, op (A,B) => A , (op B) */ ! 87: ql = l->in.left; ! 88: qr = l->in.right; ! 89: *l = *p; /* copies op, and other stuff if op is unary */ ! 90: l->in.left = qr; ! 91: p->in.right = l; ! 92: p->in.left = ql; ! 93: p->tn.op = COMOP; ! 94: rewcom( p, p->tn.goal ); ! 95: } ! 96: if( ty == UTYPE ) return; ! 97: if( r->tn.op == COMOP && r->in.right->tn.op != GENBR ) ! 98: { ! 99: /* rewrite, again */ ! 100: /* A op (B,C) => B,(A op C) */ ! 101: /* op is not unary now */ ! 102: ql = r->in.left; ! 103: qr = r->in.right; ! 104: *r = *p; ! 105: p->tn.op = COMOP; ! 106: p->in.left = ql; ! 107: r->in.right = qr; ! 108: rewcom( p, p->tn.goal ); ! 109: } ! 110: } ! 111: ! 112: rewlhs(p) ! 113: NODE *p; ! 114: ! 115: { ! 116: /* rewrite x op= y as (x op= y),x */ ! 117: /* it would be really nice to optimize after doing this . . . */ ! 118: NODE *q, *t; ! 119: q = talloc(); ! 120: *q = *p; ! 121: t = tcopy( p->in.left, 0 ); ! 122: p->in.left = q; ! 123: p->in.right = t; ! 124: p->tn.op = COMOP; ! 125: return; ! 126: } ! 127: ! 128: rewsto(p) ! 129: NODE *p; ! 130: { ! 131: /* a temp, t, is generated, and p is rewritten as ((t=p),t) */ ! 132: /* if p has the form x op= A, and x is of the right form, rewrite ! 133: /* as ((x op= A), x) */ ! 134: ! 135: int o, ao; ! 136: NODE *t, *q; ! 137: /* probably not perfect for structs: CHECK UP.. */ ! 138: ! 139: while( (o=p->tn.op) == COMOP ) p = p->in.right; ! 140: if( o == TEMP ) return(0); /* nothing to do */ ! 141: if( o == STARG ) ! 142: { ! 143: /* store a structure argument */ /* like storing a usual argument, but we have addresses */ ! 144: ! 145: t = talloc(); ! 146: *t = *p->in.left; /* copy contents, mainly for type, etc. */ ! 147: q = talloc(); ! 148: *q = *t; ! 149: t->tn.op = TEMP; ! 150: t->tn.lval = freetemp(argsize(p)/SZINT ); ! 151: t->tn.lval = BITOOR(t->tn.lval); ! 152: t->tn.name = (char *) 0; ! 153: t->tn.type = TSTRUCT; ! 154: q->tn.op = UNARY AND; ! 155: q->in.left = t; ! 156: /* now, q has & TEMP */ ! 157: t = talloc(); ! 158: *t = *p; ! 159: t->in.left = q; ! 160: t->in.right = p->in.left; ! 161: t->tn.op = STASG; ! 162: /* now, t has (&TEMP) = struct */ ! 163: p->in.left = talloc(); ! 164: p->in.left->tn.op = COMOP; ! 165: p->in.left->in.left = t; ! 166: p->in.left->in.right = t = talloc(); /* copy q here */ ! 167: *t = *q; ! 168: t->in.left = talloc(); ! 169: *t->in.left = *q->in.left; ! 170: /* finally, have (&TEMP = struct),(&TEMP) */ ! 171: /* this should do it: whew! */ ! 172: #ifndef NODBG ! 173: if( odebug>1 ) e2print( p ); ! 174: #endif ! 175: return( 1 ); ! 176: } ! 177: ! 178: #ifndef NODBG ! 179: if( odebug>1 ) ! 180: { ! 181: e2print( p ); ! 182: printf( "\nrewritten by rewsto as:\n" ); ! 183: } ! 184: #endif ! 185: if( asgop(o) && o!=INCR && o!=DECR && lhsok( p->in.left ) ) { ! 186: /* x op= y turns into (x op= y), x */ ! 187: rewlhs( p ); ! 188: return( 1 ); ! 189: } ! 190: ao = ASG o; ! 191: if( asgbinop(ao) ) ! 192: { ! 193: if( p->in.left->tn.op == TEMP ) ! 194: { ! 195: p->tn.op = ao; ! 196: rewlhs( p ); ! 197: #ifndef NODBG ! 198: if( odebug>1 ) e2print( p ); ! 199: #endif ! 200: return( 1 ); ! 201: } ! 202: } ! 203: ! 204: /* to rewrite in place, p becomes a COMOP; rhs is the temp, lsh ! 205: ** /* is t = p, where p has been converted to the intermediate type ! 206: */ ! 207: /* after some debate, the type of the temp will be the type of p */ ! 208: ! 209: t = talloc(); ! 210: *t = *p; /* copy contents, mainly for type, etc. */ ! 211: q = talloc(); ! 212: *q = *p; ! 213: t->tn.op = TEMP; ! 214: t->tn.lval = freetemp(argsize(p)/SZINT ); ! 215: t->tn.lval = BITOOR(t->tn.lval); ! 216: t->tn.name = (char *) 0; ! 217: q->tn.op = ASSIGN; ! 218: q->in.left = t; ! 219: q->in.right = talloc(); ! 220: *(q->in.right) = *p; ! 221: /* now, q has (t=p) */ ! 222: p->in.right = talloc(); ! 223: *(p->in.right) = *t; ! 224: p->tn.op = COMOP; ! 225: p->in.left = q; ! 226: /* this should do it: whew! */ ! 227: #ifndef NODBG ! 228: if( odebug>1 ) e2print( p ); ! 229: #endif ! 230: return( 1 ); ! 231: } ! 232: ! 233: iseff( p ) ! 234: NODE *p; ! 235: ! 236: { ! 237: /* return 1 if p has some side effects, 0 otherwise */ ! 238: int o; ! 239: o = p->tn.op; ! 240: if( callop(o) || asgop(o) ) return( 1 ); ! 241: switch( optype( o ) ) ! 242: { ! 243: case BITYPE: ! 244: if( iseff( p->in.right ) ) return( 1 ); ! 245: case UTYPE: ! 246: return( iseff( p->in.left ) ); ! 247: } ! 248: return( 0 ); ! 249: } ! 250: ! 251: NODE * ! 252: lhsto( p ) ! 253: NODE *p; ! 254: ! 255: { ! 256: /* find a piece of the LHS to be stored */ ! 257: /* if found, rewrite tree */ ! 258: NODE *q; ! 259: int o; ! 260: ! 261: for( q = p->in.left; (o=q->tn.op)!=STAR; q=q->in.left ) ! 262: { ! 263: if( optype(o) == LTYPE ) return( (NODE *)0); ! 264: } ! 265: /* q is now the * node, if there one */ ! 266: q = q->in.left; ! 267: o = q->tn.op; ! 268: if( optype(o) == LTYPE ) return( (NODE *)0 ); ! 269: else return( q ); ! 270: } ! 271: ! 272: static int ! 273: c2bigger( p ) NODE *p; { ! 274: /* p is a conversion op; does it make things bigger */ ! 275: register TWORD t, tl; ! 276: ! 277: t = p->tn.type; ! 278: tl = p->in.left->tn.type; ! 279: ! 280: if( (t|tl)&TPOINT ) return( 0 ); /* pointers are funny */ ! 281: if( t&TDOUBLE ) return( 1 ); ! 282: if( tl&TDOUBLE ) return( 0 ); ! 283: if( t&TFLOAT ) return( 1 ); ! 284: if( tl&TFLOAT ) return( 0 ); ! 285: if( t&(TLONG|TULONG) ) return( 1 ); ! 286: if( tl&(TLONG|TULONG) ) return( 0 ); ! 287: if( t&(TINT|TUNSIGNED) ) return( 1 ); ! 288: if( tl&(TINT|TUNSIGNED) ) return( 0 ); ! 289: if( t &(TSHORT|TUSHORT) ) return( 1 ); ! 290: return( 0 ); ! 291: } ! 292: ! 293: NODE * ! 294: ind2type( p ) ! 295: register NODE *p; ! 296: ! 297: { ! 298: /* make the type of p be the appropriate type for an argument */ ! 299: register TWORD t; ! 300: NODE *q; ! 301: ! 302: t = p->tn.type; ! 303: if( t == TCHAR || t == TSHORT ) t = TINT; ! 304: else if( t == TUCHAR || t == TUSHORT ) t = TUNSIGNED; ! 305: else if( t == TFLOAT ) t = TDOUBLE; ! 306: else return( p ); ! 307: ! 308: if( p->tn.op == CONV && c2bigger(p) ) ! 309: { ! 310: p->tn.type = t; ! 311: return( p ); ! 312: } ! 313: q = talloc(); ! 314: q->tn.op = CONV; ! 315: q->in.left = p; ! 316: q->in.right = 0; ! 317: q->tn.name = (char *) 0; ! 318: q->tn.type = t; ! 319: q->tn.goal = NRGS; ! 320: return( q ); ! 321: } ! 322: ! 323: NODE * ! 324: reweop( p ) ! 325: register NODE *p; ! 326: ! 327: { ! 328: /* rewrite A op= B as A = A op B */ ! 329: /* also, rewrite (CONV A) op= B as A = (CONV ( (CONV A) op B ) ) */ ! 330: /* rewritten in place */ ! 331: /* on input, the type of the op= equals the type of A */ ! 332: /* the type of the op node on output is the type of B */ ! 333: /* the type of the = node on output is the type of A */ ! 334: ! 335: register NODE *q, *t; ! 336: register TWORD ty; ! 337: ! 338: #ifndef NODBG ! 339: if( odebug>1 ) ! 340: { ! 341: e2print( p ); ! 342: printf( "\nrewritten by reweop as:\n" ); ! 343: } ! 344: #endif ! 345: q = tcopy( p, 0 ); ! 346: if( p->in.left->tn.op == CONV ) ! 347: { ! 348: /* ( CONV (A) ) op= B becomes A = CONV ( CONV(A) op B ) */ ! 349: /* the op is done to the type of B */ ! 350: /* the assignment is done to the type of A */ ! 351: t = p->in.left; ! 352: ty = t->in.left->tn.type; ! 353: p->in.left = t->in.left; ! 354: tfree( p->in.right ); ! 355: p->in.right = t; ! 356: t->in.left = q; ! 357: /* now, have the tree built; fix the types */ ! 358: t->tn.type = ty; ! 359: } ! 360: else ! 361: { ! 362: tfree( p->in.right ); ! 363: p->in.right = q; ! 364: } ! 365: /* NOTE: no =ops for structures... */ ! 366: p->tn.op = ASSIGN; ! 367: q->tn.op = NOASG q->tn.op; ! 368: p->tn.type = p->in.left->tn.type; ! 369: q->tn.type = q->in.right->tn.type; ! 370: #ifndef NODBG ! 371: if( odebug>1 ) e2print( p ); ! 372: #endif ! 373: } ! 374: ! 375: rewass( p ) ! 376: NODE *p; ! 377: ! 378: { ! 379: NODE *q; ! 380: int o; ! 381: /* look for =ops to be rewritten */ ! 382: ! 383: #ifndef NODBG ! 384: if( odebug ) ! 385: { ! 386: printf( "rewass called with:\n" ); ! 387: e2print( p ); ! 388: } ! 389: #endif ! 390: o = p->tn.op; ! 391: if( o == UNARY AND ) ! 392: { ! 393: if( p->in.left->tn.op == RNODE ) ! 394: { ! 395: /* this should happen only with structure returns */ ! 396: q = p->in.left; ! 397: q->tn.op = ICON; ! 398: *p = *q; ! 399: q->tn.op = FREE; ! 400: return(0); /* keep going in costs */ ! 401: } ! 402: /* this case should happen only with short structures */ ! 403: rewsto( p->in.left ); ! 404: /* & f() has turned into & ( t=f(),t) */ ! 405: #ifndef NODBG ! 406: if( odebug ) ! 407: { ! 408: printf( "\nrewritten by rewass as:\n" ); ! 409: e2print( p ); ! 410: } ! 411: #endif ! 412: return(1); ! 413: } ! 414: if( !asgop(o) || o==ASSIGN ) ! 415: { ! 416: if( o==ASSIGN ) ! 417: { ! 418: /* look for funny nodes on lhs */ ! 419: o = p->in.left->tn.op; ! 420: if( o==RNODE || o==QNODE || o==SNODE ) ! 421: { ! 422: /* force into r0 */ ! 423: p->in.left->tn.op = REG; ! 424: p->in.left->tn.rval = callreg( p->in.right ); ! 425: #ifndef NODBG ! 426: if( odebug ) ! 427: { ! 428: printf( "funny node redone\n" ); ! 429: e2print(p); ! 430: } ! 431: #endif ! 432: return(0); ! 433: } ! 434: } ! 435: else ! 436: { ! 437: TWORD t = p->in.left->tn.type; ! 438: /* this case is, for example, ! 439: unsigned char a, b; ! 440: ... a*b ! 441: /* we convert both to a reasonable type */ ! 442: /* the result is assumed to be automatically ! 443: /* converted downwards if it should be... */ ! 444: ! 445: p->in.left = ind2type( p->in.left ); ! 446: p->in.right = ind2type( p->in.right ); ! 447: #ifndef NODBG ! 448: if( odebug ) { ! 449: printf( "conversions inserted" ); ! 450: e2print(p); ! 451: } ! 452: #endif ! 453: /* if this didn't work, we are in trouble */ ! 454: if( t != p->in.left->tn.type ) { ! 455: /* we have changed something */ ! 456: return( 0 ); ! 457: } ! 458: } ! 459: e2print(p); ! 460: cerror( "can't deal with op %s", opst[o] ); ! 461: } ! 462: if( o == INCR || o == DECR ) ! 463: { ! 464: /* very crude: a++ becomes (a+=1)-1 */ ! 465: #ifndef NODBG ! 466: if( odebug>1 ) ! 467: { ! 468: e2print( p ); ! 469: printf( "\nrewritten by rewass as:\n" ); ! 470: } ! 471: #endif ! 472: if( p->in.goal == CEFF ) ! 473: { ! 474: p->in.op = ((o==INCR)?ASG PLUS:ASG MINUS); ! 475: } ! 476: else ! 477: { ! 478: q = tcopy(p, 0); ! 479: regrcl( p->in.left ); ! 480: tfree( p->in.left ); ! 481: p->in.left = q; ! 482: q->tn.op = ((o==INCR)?ASG PLUS:ASG MINUS); ! 483: p->tn.op = ((o==INCR)?MINUS:PLUS); ! 484: } ! 485: #ifndef NODBG ! 486: if( odebug ) ! 487: { ! 488: printf( "\nrewritten by rewass as:\n" ); ! 489: e2print( p ); ! 490: } ! 491: #endif ! 492: return(1); ! 493: } ! 494: /* find out if some subtree has to be stored into a temp... */ ! 495: if( q = lhsto(p) ) ! 496: { ! 497: if( !rewsto( q ) ) cerror( "rewass0" ); /* q => t=q,t */ ! 498: rewcom( p, p->tn.goal ); /* move COMOP to the top */ ! 499: if( p->tn.op != COMOP ) cerror( "rewass1" ); ! 500: if( !asgop( p->in.right->tn.op ) ) cerror( "rewass2" ); ! 501: reweop( p->in.right ); ! 502: } ! 503: else reweop( p ); /* rewrite p as an =OP */ ! 504: return(1); ! 505: } ! 506: ! 507: # ifdef NONEST ! 508: subcall( p ) ! 509: register NODE *p; ! 510: ! 511: { ! 512: /* return 1 if p contains a callop */ ! 513: register o, t; ! 514: ! 515: o = p->tn.op; ! 516: if( callop(o) ! 517: # ifndef UCALLBAD ! 518: && o!=UNARY CALL ! 519: # endif ! 520: # ifndef STCALLBAD ! 521: && o!=UNARY STCALL ! 522: # endif ! 523: # ifndef UFCALLBAD ! 524: && o!=UNARY FORTCALL ! 525: # endif ! 526: ) return( 1 ); ! 527: t = optype( o ); ! 528: if( t==BITYPE && subcall(p->in.right) ) return( 1 ); ! 529: if( t!=LTYPE ) return( subcall( p->in.left ) ); ! 530: return( 0 ); ! 531: } ! 532: ! 533: nonest( p ) ! 534: register NODE *p; ! 535: ! 536: { ! 537: register o, t; ! 538: /* right now, this is very crude */ ! 539: /* find arguments below a call; store them */ ! 540: /* nonest is called up to a call; stocm is called within args */ ! 541: ! 542: o = p->tn.op; ! 543: t = optype( o ); ! 544: if( o==CALL || o==STCALL || o==FORTCALL) ! 545: { ! 546: stocm( p->in.right ); ! 547: nonest( p->in.left ); ! 548: return; ! 549: } ! 550: if( t == BITYPE ) nonest( p->in.right ); ! 551: if( t != LTYPE ) nonest( p->in.left ); ! 552: } ! 553: ! 554: stocm( p ) ! 555: register NODE *p; ! 556: ! 557: { ! 558: /* all call arguments below p must be stored */ ! 559: register NODE *q; ! 560: register o; ! 561: ! 562: while( (o=p->tn.op) == CM ) ! 563: { ! 564: stocm( p->in.right ); ! 565: p = p->in.left; ! 566: } ! 567: if( o != STARG && o != FUNARG ) cerror( "stocm" ); ! 568: ! 569: q = p->in.left; ! 570: if( subcall( q ) ) ! 571: { ! 572: if( o == FUNARG ) rewsto( q ); ! 573: else ! 574: { ! 575: /* structure argument with call beneath */ ! 576: rewsto( p ); ! 577: } ! 578: /* now q will be done outside of a call, so use nonest */ ! 579: nonest( q ); ! 580: } ! 581: } ! 582: # endif ! 583: ! 584: outshp( pp ) ! 585: SHAPE **pp; ! 586: ! 587: { ! 588: SHAPE *p; ! 589: ! 590: if (pp == 0) ! 591: return; ! 592: ! 593: for( ; p = *pp; ++pp ) ! 594: { ! 595: printf("\t\t"); ! 596: shpr(p); ! 597: printf( " (%d)\n", p->sc ); ! 598: } ! 599: } ! 600: ! 601: tabpr() ! 602: { ! 603: register OPTAB *p; ! 604: for (p =table; ;p++) ! 605: { ! 606: printf("Dump of table[%d] (stinline %d)\n", p-table, p->stinline ); ! 607: printf("\top = %s\n", opst[p->op]); ! 608: printf("\tnextop = %d\n", p->nextop?p->nextop-table:-1 ); ! 609: printf("\tlshape = %d\n", p->lshape-pshape); ! 610: printf("\tltype = 0%o\n", p->ltype); ! 611: printf("\trshape = %d\n", p->rshape-pshape); ! 612: printf("\trtype = 0%o\n", p->rtype); ! 613: printf("\tneeds = %d\n", p->needs); ! 614: printf("\trewrite = %d\n", p->rewrite); ! 615: printf("\tcstring = %s", p->cstring); ! 616: printf("\tcost = %d\n", p->cost); ! 617: printf("\tLeft:\n"); ! 618: outshp(p->lshape); ! 619: printf("\tRight:\n"); ! 620: outshp(p->rshape); ! 621: printf("\n"); ! 622: } ! 623: } ! 624: ! 625: codgen( p ) ! 626: NODE *p; ! 627: ! 628: { ! 629: ! 630: /* generate the code for p; */ ! 631: int i, flag; ! 632: ! 633: #ifndef NODBG ! 634: if (odebug > 5) ! 635: { ! 636: tabpr(); ! 637: /* NOTREACHED */ ! 638: } ! 639: #endif ! 640: ! 641: # ifdef NONEST ! 642: nonest(p); ! 643: # endif ! 644: ! 645: /* if we make drastic changes to the tree (e.g., introduce temps) ! 646: ** /* we will go back and do the whole thing again ! 647: */ ! 648: /* statistics indicate that this happens about 10% of the time */ ! 649: /* if the percentage rises, there are many things that can be done to ! 650: ** /* improve matters ! 651: */ ! 652: /* for example, RNODE, etc., could be removed by reader, and some of ! 653: ** /* the op rewriting could be discovered by reader as well ! 654: */ ! 655: ! 656: again: ! 657: ! 658: /* move the comma ops as high as practical */ ! 659: ! 660: rewcom( p, CEFF ); ! 661: ! 662: #ifndef NODBG ! 663: if( odebug ) ! 664: { ! 665: printf( "After goals are computed:" ); ! 666: e2print( p ); ! 667: } ! 668: #endif ! 669: ! 670: /* compute the costs */ ! 671: ! 672: if( costs( p ) ) goto again; /* if rewritten, do again */ ! 673: ! 674: #ifndef NODBG ! 675: if( odebug ) ! 676: { ! 677: printf( "After costs are computed:" ); ! 678: e2print( p ); ! 679: } ! 680: #endif ! 681: ! 682: /* do a trial code generation */ ! 683: nins = 0; ! 684: insout( p, CEFF ); ! 685: ! 686: /* rewrite stored subtrees as assignments to temps, with COMOP's */ ! 687: flag = 0; ! 688: for( i=0; i<nins; ++i ) ! 689: { ! 690: if( inst[i].goal == CTEMP ) ! 691: { ! 692: #ifndef NODBG ! 693: if( odebug ) ! 694: { ! 695: printf( "subtree is stored in temp:\n" ); ! 696: e2print( inst[i].p ); ! 697: } ! 698: #endif ! 699: if( rewsto( inst[i].p ) ) { ! 700: if( !fast ) goto again; ! 701: /* otherwise, rewrite all temps now */ ! 702: flag = 1; ! 703: } ! 704: } ! 705: } ! 706: if( flag ) goto again; ! 707: ! 708: #ifndef NODBG ! 709: if( odebug ) e2print(p); ! 710: #endif ! 711: /* output the actual instructions */ ! 712: insprt(); ! 713: } ! 714: ! 715: INST inst[NINS]; ! 716: int nins; ! 717: ! 718: insprt() ! 719: { ! 720: int i; ! 721: register INST *pi; ! 722: register NODE *p; ! 723: register OPTAB *q; ! 724: register c, goal; ! 725: ! 726: for( pi=inst,i=0; i<nins; ++i,++pi ) ! 727: { ! 728: p = pi->p; ! 729: q = pi->q; ! 730: c = pi->goal; ! 731: if( c == CCC && (q->rewrite&RESCC) ) goal = FORCC; ! 732: else if( c == CEFF ) goal = FOREFF; ! 733: else goal = INREG; ! 734: #ifndef NODEBUG ! 735: if(odebug > 4) ! 736: { ! 737: printf("INSOUT: %d c=",i); ! 738: preff(c); ! 739: printf(" goal="); ! 740: prgoal(goal); ! 741: printf("\n"); ! 742: e2print(p); ! 743: } ! 744: #endif ! 745: ! 746: allo( p, q ); ! 747: # ifdef TMPSRET ! 748: /* not the best place in the world, but... */ ! 749: if (p->in.op == STCALL || p->in.op == UNARY STCALL) ! 750: expand(p, goal, TMPSRET, q); ! 751: #endif ! 752: expand( p, goal, q->cstring, q ); ! 753: reclaim( p, q->rewrite, goal ); ! 754: ! 755: /* now, if condition codes needed, test */ ! 756: if( c == CCC && p->tn.op != CCODES ) ! 757: { ! 758: cfix( p, CCC ); ! 759: if( p->tn.op != CCODES ) cerror( "ctest fails" ); ! 760: } ! 761: if( c>=0 && c<=NRGS && !istnode( p ) ) ! 762: { ! 763: cfix( p, NRGS ); ! 764: } ! 765: } ! 766: } ! 767: ! 768: SHTABLE sha; ! 769: ! 770: cfix( p, goal ) ! 771: NODE *p; ! 772: { ! 773: /* p is to be fixed according to goal (CCC or NRGS) */ ! 774: OPTAB *q; ! 775: NODE *pp; ! 776: int r; ! 777: ! 778: #ifndef NODBG ! 779: if(odebug > 4) ! 780: { ! 781: printf("CFIX: goal="); ! 782: prgoal(goal); ! 783: printf("\n"); ! 784: e2print(p); ! 785: } ! 786: #endif ! 787: if( goal == CCC ) ! 788: { ! 789: r = RESCC; ! 790: p->tn.goal = CCC; ! 791: } ! 792: else ! 793: { ! 794: r = (RESC1|RESC2|RESC3); ! 795: pp = getl( p ); ! 796: if( istnode( pp ) ) r |= RLEFT; ! 797: pp = getr( p ); ! 798: if( istnode( pp ) ) r |= RRIGHT; ! 799: } ! 800: ! 801: if( goal == CCC ) goal = FORCC; ! 802: else goal = INREG; ! 803: ! 804: for( q=0; q = match( p, q ); ) ! 805: { ! 806: /* takes the first match (may not be cheapest) */ ! 807: /* template writers, take note! */ ! 808: if( q->rewrite & r ) ! 809: { ! 810: /* generate the code on the spot */ ! 811: allo( p, q ); ! 812: # ifdef TMPSRET ! 813: /* likewise */ ! 814: if (p->in.op == STCALL || p->in.op == UNARY STCALL) ! 815: expand(p, goal, TMPSRET, q); ! 816: #endif ! 817: expand( p, goal, q->cstring, q ); ! 818: reclaim( p, q->rewrite, goal ); ! 819: return; ! 820: } ! 821: } ! 822: e2print(p); ! 823: cerror( "cfix trouble" ); ! 824: } ! 825: ! 826: ! 827: preff(c) ! 828: { ! 829: char buf[20]; ! 830: register char *p; ! 831: ! 832: p = c==CCC ? "CCC" : c==CTEMP ? "CTEMP" : c==CEFF ? "CEFF" : 0; ! 833: if(!p) ! 834: { ! 835: sprintf(buf,"0%o",c); ! 836: p = buf; ! 837: } ! 838: printf("%s",p); ! 839: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.