|
|
1.1 ! root 1: /* @(#) cgen.c: 1.3 4/26/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 ); ! 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: if ( !p ) ! 303: return( p ); ! 304: t = p->tn.type; ! 305: if( t == TCHAR || t == TSHORT ) t = TINT; ! 306: else if( t == TUCHAR || t == TUSHORT ) t = TUNSIGNED; ! 307: else if( t == TFLOAT ) t = TDOUBLE; ! 308: else return( p ); ! 309: ! 310: if( p->tn.op == CONV && c2bigger(p) ) ! 311: { ! 312: p->tn.type = t; ! 313: return( p ); ! 314: } ! 315: q = talloc(); ! 316: q->tn.op = CONV; ! 317: q->in.left = p; ! 318: q->in.right = 0; ! 319: q->tn.name = (char *) 0; ! 320: q->tn.type = t; ! 321: q->tn.goal = NRGS; ! 322: return( q ); ! 323: } ! 324: ! 325: NODE * ! 326: reweop( p ) ! 327: register NODE *p; ! 328: ! 329: { ! 330: /* rewrite A op= B as A = A op B */ ! 331: /* also, rewrite (CONV A) op= B as A = (CONV ( (CONV A) op B ) ) */ ! 332: /* rewritten in place */ ! 333: /* on input, the type of the op= equals the type of A */ ! 334: /* the type of the op node on output is the type of B */ ! 335: /* the type of the = node on output is the type of A */ ! 336: ! 337: register NODE *q, *t; ! 338: register TWORD ty; ! 339: ! 340: #ifndef NODBG ! 341: if( odebug>1 ) ! 342: { ! 343: e2print( p ); ! 344: printf( "\nrewritten by reweop as:\n" ); ! 345: } ! 346: #endif ! 347: /* rewrite tree with duplicate left subtree in new right subtree */ ! 348: /* there is an implicit q->in.right = p->in.right in *q = *p */ ! 349: q = talloc(); ! 350: *q = *p; ! 351: q->in.left = tcopy( p->in.left ); ! 352: if( p->in.left->tn.op == CONV ) ! 353: { ! 354: /* ( CONV (A) ) op= B becomes A = CONV ( CONV(A) op B ) */ ! 355: /* the op is done to the type of B */ ! 356: /* the assignment is done to the type of A */ ! 357: t = p->in.left; ! 358: ty = t->in.left->tn.type; ! 359: p->in.left = t->in.left; ! 360: p->in.right = t; ! 361: t->in.left = q; ! 362: /* now, have the tree built; fix the types */ ! 363: t->tn.type = ty; ! 364: } ! 365: else ! 366: { ! 367: p->in.right = q; ! 368: } ! 369: /* NOTE: no =ops for structures... */ ! 370: p->tn.op = ASSIGN; ! 371: q->tn.op = NOASG q->tn.op; ! 372: p->tn.type = p->in.left->tn.type; ! 373: q->tn.type = q->in.right->tn.type; ! 374: #ifndef NODBG ! 375: if( odebug>1 ) e2print( p ); ! 376: #endif ! 377: } ! 378: ! 379: rewass( p ) ! 380: NODE *p; ! 381: ! 382: { ! 383: NODE *q; ! 384: int o; ! 385: /* look for =ops to be rewritten */ ! 386: ! 387: #ifndef NODBG ! 388: if( odebug ) ! 389: { ! 390: printf( "rewass called with:\n" ); ! 391: e2print( p ); ! 392: } ! 393: #endif ! 394: o = p->tn.op; ! 395: if( o == UNARY AND ) ! 396: { ! 397: if( p->in.left->tn.op == RNODE ) ! 398: { ! 399: /* this should happen only with structure returns */ ! 400: q = p->in.left; ! 401: q->tn.op = ICON; ! 402: *p = *q; ! 403: q->tn.op = FREE; ! 404: return(0); /* keep going in costs */ ! 405: } ! 406: /* this case should happen only with short structures */ ! 407: rewsto( p->in.left ); ! 408: /* & f() has turned into & ( t=f(),t) */ ! 409: #ifndef NODBG ! 410: if( odebug ) ! 411: { ! 412: printf( "\nrewritten by rewass as:\n" ); ! 413: e2print( p ); ! 414: } ! 415: #endif ! 416: return(1); ! 417: } ! 418: if( !asgop(o) || o==ASSIGN ) ! 419: { ! 420: if( o==ASSIGN ) ! 421: { ! 422: /* look for funny nodes on lhs */ ! 423: o = p->in.left->tn.op; ! 424: if( o==RNODE || o==QNODE || o==SNODE ) ! 425: { ! 426: /* force into r0 */ ! 427: p->in.left->tn.op = REG; ! 428: p->in.left->tn.rval = callreg( p->in.right ); ! 429: #ifndef NODBG ! 430: if( odebug ) ! 431: { ! 432: printf( "funny node redone\n" ); ! 433: e2print(p); ! 434: } ! 435: #endif ! 436: return(0); ! 437: } ! 438: } ! 439: else ! 440: { ! 441: TWORD t = p->in.left->tn.type; ! 442: /* this case is, for example, ! 443: unsigned char a, b; ! 444: ... a*b ! 445: /* we convert both to a reasonable type */ ! 446: /* the result is assumed to be automatically ! 447: /* converted downwards if it should be... */ ! 448: ! 449: p->in.left = ind2type( p->in.left ); ! 450: p->in.right = ind2type( p->in.right ); ! 451: #ifndef NODBG ! 452: if( odebug ) { ! 453: printf( "conversions inserted" ); ! 454: e2print(p); ! 455: } ! 456: #endif ! 457: /* if this didn't work, we are in trouble */ ! 458: if( t != p->in.left->tn.type ) { ! 459: /* we have changed something */ ! 460: return( 0 ); ! 461: } ! 462: } ! 463: e2print(p); ! 464: cerror( "can't deal with op %s", opst[o] ); ! 465: } ! 466: if( o == INCR || o == DECR ) ! 467: { ! 468: /* very crude: a++ becomes (a+=1)-1 */ ! 469: #ifndef NODBG ! 470: if( odebug>1 ) ! 471: { ! 472: e2print( p ); ! 473: printf( "\nrewritten by rewass as:\n" ); ! 474: } ! 475: #endif ! 476: if( p->in.goal == CEFF ) ! 477: { ! 478: p->in.op = ((o==INCR)?ASG PLUS:ASG MINUS); ! 479: } ! 480: else ! 481: { ! 482: /* rewrite tree with duplicate left subree in new ! 483: /* right subtree... ! 484: /* there is an implict q->in.left = p->in.left in *q = * p ! 485: */ ! 486: q = talloc(); ! 487: *q = *p; ! 488: q->in.right = tcopy( p->in.right ); ! 489: p->in.left = q; ! 490: q->tn.op = ((o==INCR)?ASG PLUS:ASG MINUS); ! 491: p->tn.op = ((o==INCR)?MINUS:PLUS); ! 492: } ! 493: #ifndef NODBG ! 494: if( odebug ) ! 495: { ! 496: printf( "\nrewritten by rewass as:\n" ); ! 497: e2print( p ); ! 498: } ! 499: #endif ! 500: return(1); ! 501: } ! 502: /* find out if some subtree has to be stored into a temp... */ ! 503: if( q = lhsto(p) ) ! 504: { ! 505: if( !rewsto( q ) ) cerror( "rewass0" ); /* q => t=q,t */ ! 506: rewcom( p, p->tn.goal ); /* move COMOP to the top */ ! 507: if( p->tn.op != COMOP ) cerror( "rewass1" ); ! 508: if( !asgop( p->in.right->tn.op ) ) cerror( "rewass2" ); ! 509: reweop( p->in.right ); ! 510: } ! 511: else reweop( p ); /* rewrite p as an =OP */ ! 512: return(1); ! 513: } ! 514: ! 515: # ifdef NONEST ! 516: subcall( p ) ! 517: register NODE *p; ! 518: ! 519: { ! 520: /* return 1 if p contains a callop */ ! 521: register o, t; ! 522: ! 523: o = p->tn.op; ! 524: if( callop(o) ! 525: # ifndef UCALLBAD ! 526: && o!=UNARY CALL ! 527: # endif ! 528: # ifndef STCALLBAD ! 529: && o!=UNARY STCALL ! 530: # endif ! 531: # ifndef UFCALLBAD ! 532: && o!=UNARY FORTCALL ! 533: # endif ! 534: ) return( 1 ); ! 535: t = optype( o ); ! 536: if( t==BITYPE && subcall(p->in.right) ) return( 1 ); ! 537: if( t!=LTYPE ) return( subcall( p->in.left ) ); ! 538: return( 0 ); ! 539: } ! 540: ! 541: nonest( p ) ! 542: register NODE *p; ! 543: ! 544: { ! 545: register o, t; ! 546: /* right now, this is very crude */ ! 547: /* find arguments below a call; store them */ ! 548: /* nonest is called up to a call; stocm is called within args */ ! 549: ! 550: o = p->tn.op; ! 551: t = optype( o ); ! 552: if( o==CALL || o==STCALL || o==FORTCALL) ! 553: { ! 554: stocm( p->in.right ); ! 555: nonest( p->in.left ); ! 556: return; ! 557: } ! 558: if( t == BITYPE ) nonest( p->in.right ); ! 559: if( t != LTYPE ) nonest( p->in.left ); ! 560: } ! 561: ! 562: stocm( p ) ! 563: register NODE *p; ! 564: ! 565: { ! 566: /* all call arguments below p must be stored */ ! 567: register NODE *q; ! 568: register o; ! 569: ! 570: while( (o=p->tn.op) == CM ) ! 571: { ! 572: stocm( p->in.right ); ! 573: p = p->in.left; ! 574: } ! 575: if( o != STARG && o != FUNARG ) cerror( "stocm" ); ! 576: ! 577: q = p->in.left; ! 578: if( subcall( q ) ) ! 579: { ! 580: if( o == FUNARG ) rewsto( q ); ! 581: else ! 582: { ! 583: /* structure argument with call beneath */ ! 584: rewsto( p ); ! 585: } ! 586: /* now q will be done outside of a call, so use nonest */ ! 587: nonest( q ); ! 588: } ! 589: } ! 590: # endif ! 591: ! 592: outshp( pp ) ! 593: SHAPE **pp; ! 594: ! 595: { ! 596: SHAPE *p; ! 597: ! 598: if (pp == 0) ! 599: return; ! 600: ! 601: for( ; p = *pp; ++pp ) ! 602: { ! 603: printf("\t\t"); ! 604: shpr(p); ! 605: printf( " (%d)\n", p->sc ); ! 606: } ! 607: } ! 608: ! 609: tabpr() ! 610: { ! 611: register OPTAB *p; ! 612: for (p =table; ;p++) ! 613: { ! 614: printf("Dump of table[%d] (stinline %d)\n", p-table, p->stinline ); ! 615: printf("\top = %s\n", opst[p->op]); ! 616: printf("\tnextop = %d\n", p->nextop?p->nextop-table:-1 ); ! 617: printf("\tlshape = %d\n", p->lshape-pshape); ! 618: printf("\tltype = 0%o\n", p->ltype); ! 619: printf("\trshape = %d\n", p->rshape-pshape); ! 620: printf("\trtype = 0%o\n", p->rtype); ! 621: printf("\tneeds = %d\n", p->needs); ! 622: printf("\trewrite = %d\n", p->rewrite); ! 623: printf("\tcstring = %s", p->cstring); ! 624: printf("\tcost = %d\n", p->cost); ! 625: printf("\tLeft:\n"); ! 626: outshp(p->lshape); ! 627: printf("\tRight:\n"); ! 628: outshp(p->rshape); ! 629: printf("\n"); ! 630: } ! 631: } ! 632: ! 633: codgen( p ) ! 634: NODE *p; ! 635: ! 636: { ! 637: ! 638: /* generate the code for p; */ ! 639: int i, flag; ! 640: ! 641: #ifndef NODBG ! 642: if (odebug > 5) ! 643: { ! 644: tabpr(); ! 645: /* NOTREACHED */ ! 646: } ! 647: #endif ! 648: ! 649: # ifdef NONEST ! 650: nonest(p); ! 651: # endif ! 652: ! 653: /* if we make drastic changes to the tree (e.g., introduce temps) ! 654: ** /* we will go back and do the whole thing again ! 655: */ ! 656: /* statistics indicate that this happens about 10% of the time */ ! 657: /* if the percentage rises, there are many things that can be done to ! 658: ** /* improve matters ! 659: */ ! 660: /* for example, RNODE, etc., could be removed by reader, and some of ! 661: ** /* the op rewriting could be discovered by reader as well ! 662: */ ! 663: ! 664: again: ! 665: ! 666: /* move the comma ops as high as practical */ ! 667: ! 668: rewcom( p, CEFF ); ! 669: ! 670: #ifndef NODBG ! 671: if( odebug ) ! 672: { ! 673: printf( "After goals are computed:" ); ! 674: e2print( p ); ! 675: } ! 676: #endif ! 677: ! 678: /* compute the costs */ ! 679: ! 680: if( costs( p ) ) goto again; /* if rewritten, do again */ ! 681: ! 682: #ifndef NODBG ! 683: if( odebug ) ! 684: { ! 685: printf( "After costs are computed:" ); ! 686: e2print( p ); ! 687: } ! 688: #endif ! 689: ! 690: /* do a trial code generation */ ! 691: nins = 0; ! 692: insout( p, CEFF ); ! 693: ! 694: /* rewrite stored subtrees as assignments to temps, with COMOP's */ ! 695: flag = 0; ! 696: for( i=0; i<nins; ++i ) ! 697: { ! 698: if( inst[i].goal == CTEMP ) ! 699: { ! 700: #ifndef NODBG ! 701: if( odebug ) ! 702: { ! 703: printf( "subtree is stored in temp:\n" ); ! 704: e2print( inst[i].p ); ! 705: } ! 706: #endif ! 707: if( rewsto( inst[i].p ) ) { ! 708: if( !fast ) goto again; ! 709: /* otherwise, rewrite all temps now */ ! 710: flag = 1; ! 711: } ! 712: } ! 713: } ! 714: if( flag ) goto again; ! 715: ! 716: #ifndef NODBG ! 717: if( odebug ) e2print(p); ! 718: #endif ! 719: /* output the actual instructions */ ! 720: insprt(); ! 721: } ! 722: ! 723: INST inst[NINS]; ! 724: int nins; ! 725: ! 726: insprt() ! 727: { ! 728: int i; ! 729: register INST *pi; ! 730: register NODE *p; ! 731: register OPTAB *q; ! 732: register c, goal; ! 733: ! 734: for( pi=inst,i=0; i<nins; ++i,++pi ) ! 735: { ! 736: p = pi->p; ! 737: q = pi->q; ! 738: c = pi->goal; ! 739: if( c == CCC && (q->rewrite&RESCC) ) goal = FORCC; ! 740: else if( c == CEFF ) goal = FOREFF; ! 741: else goal = INREG; ! 742: #ifndef NODEBUG ! 743: if(odebug > 4) ! 744: { ! 745: printf("INSOUT: %d c=",i); ! 746: preff(c); ! 747: printf(" goal="); ! 748: prgoal(goal); ! 749: printf("\n"); ! 750: e2print(p); ! 751: } ! 752: #endif ! 753: ! 754: allo( p, q ); ! 755: # ifdef TMPSRET ! 756: /* not the best place in the world, but... */ ! 757: if (p->in.op == STCALL || p->in.op == UNARY STCALL) ! 758: expand(p, goal, TMPSRET, q); ! 759: #endif ! 760: expand( p, goal, q->cstring, q ); ! 761: reclaim( p, q->rewrite, goal ); ! 762: ! 763: /* now, if condition codes needed, test */ ! 764: if( c == CCC && p->tn.op != CCODES ) ! 765: { ! 766: cfix( p, CCC ); ! 767: if( p->tn.op != CCODES ) cerror( "ctest fails" ); ! 768: } ! 769: if( c>=0 && c<=NRGS && !istnode( p ) ) ! 770: { ! 771: cfix( p, NRGS ); ! 772: } ! 773: } ! 774: } ! 775: ! 776: SHTABLE sha; ! 777: int odebug = 0; ! 778: ! 779: cfix( p, goal ) ! 780: NODE *p; ! 781: { ! 782: /* p is to be fixed according to goal (CCC or NRGS) */ ! 783: OPTAB *q; ! 784: NODE *pp; ! 785: int r; ! 786: ! 787: #ifndef NODBG ! 788: if(odebug > 4) ! 789: { ! 790: printf("CFIX: goal="); ! 791: prgoal(goal); ! 792: printf("\n"); ! 793: e2print(p); ! 794: } ! 795: #endif ! 796: if( goal == CCC ) ! 797: { ! 798: r = RESCC; ! 799: p->tn.goal = CCC; ! 800: } ! 801: else ! 802: { ! 803: r = (RESC1|RESC2|RESC3); ! 804: pp = getl( p ); ! 805: if( istnode( pp ) ) r |= RLEFT; ! 806: pp = getr( p ); ! 807: if( istnode( pp ) ) r |= RRIGHT; ! 808: } ! 809: ! 810: if( goal == CCC ) goal = FORCC; ! 811: else goal = INREG; ! 812: ! 813: for( q=0; q = match( p, q ); ) ! 814: { ! 815: /* takes the first match (may not be cheapest) */ ! 816: /* template writers, take note! */ ! 817: if( q->rewrite & r ) ! 818: { ! 819: /* generate the code on the spot */ ! 820: allo( p, q ); ! 821: # ifdef TMPSRET ! 822: /* likewise */ ! 823: if (p->in.op == STCALL || p->in.op == UNARY STCALL) ! 824: expand(p, goal, TMPSRET, q); ! 825: #endif ! 826: expand( p, goal, q->cstring, q ); ! 827: reclaim( p, q->rewrite, goal ); ! 828: return; ! 829: } ! 830: } ! 831: e2print(p); ! 832: cerror( "cfix trouble" ); ! 833: } ! 834: ! 835: ! 836: preff(c) ! 837: { ! 838: char buf[20]; ! 839: register char *p; ! 840: ! 841: p = c==CCC ? "CCC" : c==CTEMP ? "CTEMP" : c==CEFF ? "CEFF" : 0; ! 842: if(!p) ! 843: { ! 844: sprintf(buf,"0%o",c); ! 845: p = buf; ! 846: } ! 847: printf("%s",p); ! 848: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.