|
|
1.1 ! root 1: /* %W% (Berkeley) %G% */ ! 2: #include "defs.h" ! 3: #include "optim.h" ! 4: ! 5: ! 6: ! 7: /* ! 8: * Information buffered for each slot type ! 9: * ! 10: * slot type expptr integer pointer ! 11: * ! 12: * IFN expr label - ! 13: * GOTO - label - ! 14: * LABEL - label - ! 15: * EQ expr - - ! 16: * CALL expr - - ! 17: * CMGOTO expr num labellist* ! 18: * STOP expr - - ! 19: * DOHEAD [1] - ctlframe* ! 20: * ENDDO [1] - ctlframe* ! 21: * ARIF expr - labellist* ! 22: * RETURN expr label - ! 23: * ASGOTO expr - labellist* ! 24: * PAUSE expr - - ! 25: * ASSIGN expr label - ! 26: * SKIOIFN expr label - ! 27: * SKFRTEMP expr - - ! 28: * ! 29: * Note [1]: the nullslot field is a pointer to a fake slot which is ! 30: * at the end of the slots which may be replaced by this slot. In ! 31: * other words, it looks like this: ! 32: * DOHEAD slot ! 33: * slot \ ! 34: * slot > ordinary IF, GOTO, LABEL slots which implement the DO ! 35: * slot / ! 36: * NULL slot ! 37: */ ! 38: ! 39: ! 40: expptr expand(); ! 41: ! 42: Slotp firstslot = NULL; ! 43: Slotp lastslot = NULL; ! 44: int numslots = 0; ! 45: ! 46: ! 47: /* ! 48: * turns off optimization option ! 49: */ ! 50: ! 51: optoff() ! 52: ! 53: { ! 54: flushopt(); ! 55: optimflag = 0; ! 56: } ! 57: ! 58: ! 59: ! 60: /* ! 61: * initializes the code buffer for optimization ! 62: */ ! 63: ! 64: setopt() ! 65: ! 66: { ! 67: register Slotp sp; ! 68: ! 69: for (sp = firstslot; sp; sp = sp->next) ! 70: free ( (charptr) sp); ! 71: firstslot = lastslot = NULL; ! 72: numslots = 0; ! 73: } ! 74: ! 75: ! 76: ! 77: /* ! 78: * flushes the code buffer ! 79: */ ! 80: ! 81: LOCAL int alreadycalled = 0; ! 82: ! 83: flushopt() ! 84: { ! 85: register Slotp sp; ! 86: int savelineno; ! 87: ! 88: if (alreadycalled) return; /* to prevent recursive call during errors */ ! 89: alreadycalled = 1; ! 90: ! 91: if (debugflag[1]) ! 92: showbuffer (); ! 93: ! 94: frtempbuff (); ! 95: ! 96: savelineno = lineno; ! 97: for (sp = firstslot; sp; sp = sp->next) ! 98: { ! 99: putopt(sp); ! 100: if(sp->ctlinfo) free ( (charptr) sp->ctlinfo); ! 101: free ( (charptr) sp); ! 102: numslots--; ! 103: } ! 104: firstslot = lastslot = NULL; ! 105: numslots = 0; ! 106: clearbb(); ! 107: lineno = savelineno; ! 108: ! 109: alreadycalled = 0; ! 110: } ! 111: ! 112: ! 113: ! 114: /* ! 115: * puts out code for the given slot (from the code buffer) ! 116: */ ! 117: ! 118: LOCAL putopt (sp) ! 119: register Slotp sp; ! 120: { ! 121: p2flush(); ! 122: lineno = sp->lineno; ! 123: switch (sp->type) { ! 124: case SKNULL: ! 125: break; ! 126: case SKIFN: ! 127: case SKIOIFN: ! 128: putif(sp->expr, sp->label); ! 129: break; ! 130: case SKGOTO: ! 131: putgoto(sp->label); ! 132: break; ! 133: case SKCMGOTO: ! 134: putcmgo(sp->expr, sp->label, sp->ctlinfo); ! 135: break; ! 136: case SKCALL: ! 137: putexpr(sp->expr); ! 138: break; ! 139: case SKSTOP: ! 140: putexpr (call1 (TYSUBR, "s_stop", sp->expr)); ! 141: break; ! 142: case SKPAUSE: ! 143: putexpr (call1 (TYSUBR, "s_paus", sp->expr)); ! 144: break; ! 145: case SKASSIGN: ! 146: puteq (sp->expr, mkaddcon(sp->label)); ! 147: break; ! 148: case SKDOHEAD: ! 149: case SKENDDO: ! 150: break; ! 151: case SKEQ: ! 152: putexpr(sp->expr); ! 153: break; ! 154: case SKARIF: ! 155: #define LM ((struct Labelblock * *)sp->ctlinfo)[0]->labelno ! 156: #define LZ ((struct Labelblock * *)sp->ctlinfo)[1]->labelno ! 157: #define LP ((struct Labelblock * *)sp->ctlinfo)[2]->labelno ! 158: prarif(sp->expr, LM, LZ, LP); ! 159: break; ! 160: case SKASGOTO: ! 161: putbranch((Addrp) sp->expr); ! 162: break; ! 163: case SKLABEL: ! 164: putlabel(sp->label); ! 165: break; ! 166: case SKRETURN: ! 167: if (sp->expr) ! 168: { ! 169: putforce(TYINT, sp->expr); ! 170: putgoto(sp->label); ! 171: } ! 172: else ! 173: putgoto(sp->label); ! 174: break; ! 175: case SKFRTEMP: ! 176: templist = mkchain (sp->expr,templist); ! 177: break; ! 178: default: ! 179: badthing("SKtype", "putopt", sp->type); ! 180: break; ! 181: } ! 182: } ! 183: ! 184: ! 185: ! 186: /* ! 187: * copies one element of the control stack ! 188: */ ! 189: ! 190: LOCAL struct Ctlframe *cpframe(p) ! 191: register char *p; ! 192: { ! 193: static int size = sizeof (struct Ctlframe); ! 194: register int n; ! 195: register char *q; ! 196: struct Ctlframe *q0; ! 197: ! 198: q0 = ALLOC(Ctlframe); ! 199: q = (char *) q0; ! 200: n = size; ! 201: while(n-- > 0) ! 202: *q++ = *p++; ! 203: return( q0); ! 204: } ! 205: ! 206: ! 207: ! 208: /* ! 209: * copies an array of labelblock pointers ! 210: */ ! 211: ! 212: LOCAL struct Labelblock **cplabarr(n,arr) ! 213: struct Labelblock *arr[]; ! 214: int n; ! 215: { ! 216: struct Labelblock **newarr; ! 217: register char *in, *out; ! 218: register int i,j; ! 219: ! 220: newarr = (struct Labelblock **) ckalloc (n * sizeof (char *)); ! 221: for (i = 0; i < n; i++) ! 222: { ! 223: newarr[i] = ALLOC (Labelblock); ! 224: out = (char *) newarr[i]; ! 225: in = (char *) arr[i]; ! 226: j = sizeof (struct Labelblock); ! 227: while (j-- > 0) ! 228: *out++ = *in++; ! 229: } ! 230: return (newarr); ! 231: } ! 232: ! 233: ! 234: ! 235: /* ! 236: * creates a new slot in the code buffer ! 237: */ ! 238: ! 239: LOCAL Slotp newslot() ! 240: { ! 241: register Slotp sp; ! 242: ! 243: ++numslots; ! 244: sp = ALLOC( slt ); ! 245: sp->next = NULL ; ! 246: if (lastslot) ! 247: { ! 248: sp->prev = lastslot; ! 249: lastslot = lastslot->next = sp; ! 250: } ! 251: else ! 252: { ! 253: firstslot = lastslot = sp; ! 254: sp->prev = NULL; ! 255: } ! 256: sp->lineno = lineno; ! 257: return (sp); ! 258: } ! 259: ! 260: ! 261: ! 262: /* ! 263: * removes (but not deletes) the specified slot from the code buffer ! 264: */ ! 265: ! 266: removeslot (sl) ! 267: Slotp sl; ! 268: ! 269: { ! 270: if (sl->next) ! 271: sl->next->prev = sl->prev; ! 272: else ! 273: lastslot = sl->prev; ! 274: if (sl->prev) ! 275: sl->prev->next = sl->next; ! 276: else ! 277: firstslot = sl->next; ! 278: sl->next = sl->prev = NULL; ! 279: ! 280: --numslots; ! 281: } ! 282: ! 283: ! 284: ! 285: /* ! 286: * inserts slot s1 before existing slot s2 in the code buffer; ! 287: * appends to end of list if s2 is NULL. ! 288: */ ! 289: ! 290: insertslot (s1,s2) ! 291: Slotp s1,s2; ! 292: ! 293: { ! 294: if (s2) ! 295: { ! 296: if (s2->prev) ! 297: s2->prev->next = s1; ! 298: else ! 299: firstslot = s1; ! 300: s1->prev = s2->prev; ! 301: s2->prev = s1; ! 302: } ! 303: else ! 304: { ! 305: s1->prev = lastslot; ! 306: lastslot->next = s1; ! 307: lastslot = s1; ! 308: } ! 309: s1->next = s2; ! 310: ! 311: ++numslots; ! 312: } ! 313: ! 314: ! 315: ! 316: /* ! 317: * deletes the specified slot from the code buffer ! 318: */ ! 319: ! 320: delslot (sl) ! 321: Slotp sl; ! 322: ! 323: { ! 324: removeslot (sl); ! 325: ! 326: if (sl->ctlinfo) ! 327: free ((charptr) sl->ctlinfo); ! 328: frexpr (sl->expr); ! 329: free ((charptr) sl); ! 330: numslots--; ! 331: } ! 332: ! 333: ! 334: ! 335: /* ! 336: * inserts a slot before the specified slot; if given NULL, it is ! 337: * inserted at the end of the buffer ! 338: */ ! 339: ! 340: Slotp optinsert (type,p,l,c,currslot) ! 341: int type; ! 342: expptr p; ! 343: int l; ! 344: int *c; ! 345: Slotp currslot; ! 346: ! 347: { ! 348: Slotp savelast,new; ! 349: ! 350: savelast = lastslot; ! 351: if (currslot) ! 352: lastslot = currslot->prev; ! 353: new = optbuff (type,p,l,c); ! 354: new->next = currslot; ! 355: if (currslot) ! 356: currslot->prev = new; ! 357: new->lineno = -1; /* who knows what the line number should be ??!! */ ! 358: lastslot = savelast; ! 359: return (new); ! 360: } ! 361: ! 362: ! 363: ! 364: /* ! 365: * buffers the FRTEMP slots which have been waiting ! 366: */ ! 367: ! 368: frtempbuff () ! 369: ! 370: { ! 371: chainp ht; ! 372: register Slotp sp; ! 373: ! 374: for (ht = holdtemps; ht; ht = ht->nextp) ! 375: { ! 376: sp = newslot(); ! 377: /* this slot actually belongs to some previous source line */ ! 378: sp->lineno = sp->lineno - 1; ! 379: sp->type = SKFRTEMP; ! 380: sp->expr = (expptr) ht->datap; ! 381: sp->label = 0; ! 382: sp->ctlinfo = NULL; ! 383: } ! 384: holdtemps = NULL; ! 385: } ! 386: ! 387: ! 388: ! 389: /* ! 390: * puts the given information into a slot at the end of the code buffer ! 391: */ ! 392: ! 393: Slotp optbuff (type,p,l,c) ! 394: int type; ! 395: expptr p; ! 396: int l; ! 397: int *c; ! 398: ! 399: { ! 400: register Slotp sp; ! 401: ! 402: if (debugflag[1]) ! 403: { ! 404: fprintf (diagfile,"-----optbuff-----"); showslottype (type); ! 405: showexpr (p,0); fprintf (diagfile,"\n"); ! 406: } ! 407: ! 408: p = expand (p); ! 409: sp = newslot(); ! 410: sp->type = type; ! 411: sp->expr = p; ! 412: sp->label = l; ! 413: sp->ctlinfo = NULL; ! 414: switch (type) ! 415: { ! 416: case SKCMGOTO: ! 417: sp->ctlinfo = (int*) cplabarr (l, (struct Labelblock**) c); ! 418: break; ! 419: case SKARIF: ! 420: sp->ctlinfo = (int*) cplabarr (3, (struct Labelblock**) c); ! 421: break; ! 422: case SKDOHEAD: ! 423: case SKENDDO: ! 424: sp->ctlinfo = (int*) cpframe ((struct Ctlframe*) c); ! 425: break; ! 426: default: ! 427: break; ! 428: } ! 429: ! 430: frtempbuff (); ! 431: ! 432: return (sp); ! 433: } ! 434: ! 435: ! 436: ! 437: /* ! 438: * expands the given expression, if possible (e.g., concat, min, max, etc.); ! 439: * also frees temporaries when they are indicated as being the last use ! 440: */ ! 441: ! 442: #define APPEND(z) \ ! 443: res = res->exprblock.rightp = mkexpr (OPCOMMA, z, newtemp) ! 444: ! 445: LOCAL expptr expand (p) ! 446: tagptr p; ! 447: ! 448: { ! 449: Addrp t; ! 450: expptr q; ! 451: Addrp buffmnmx(), buffpower(); ! 452: ! 453: if (!p) ! 454: return (ENULL); ! 455: switch (p->tag) ! 456: { ! 457: case TEXPR: ! 458: p->exprblock.leftp = expand (p->exprblock.leftp); ! 459: if (p->exprblock.rightp) ! 460: p->exprblock.rightp = expand (p->exprblock.rightp); ! 461: switch (p->exprblock.opcode) ! 462: { ! 463: expptr temp; ! 464: case OPCONCAT: ! 465: t = mktemp (TYCHAR, ICON(lencat(p))); ! 466: q = (expptr) cpexpr (p->exprblock.vleng); ! 467: buffcat (cpexpr(t),p); ! 468: frexpr (t->vleng); ! 469: t->vleng = q; ! 470: p = (tagptr) t; ! 471: break; ! 472: case OPMIN: ! 473: case OPMAX: ! 474: p = (tagptr) buffmnmx (p); ! 475: break; ! 476: case OPPOWER: ! 477: p = (tagptr) buffpower (p); ! 478: break; ! 479: default: ! 480: break; ! 481: } ! 482: break; ! 483: ! 484: case TLIST: ! 485: { ! 486: chainp t; ! 487: for (t = p->listblock.listp; t; t = t->nextp) ! 488: t->datap = (tagptr) expand (t->datap); ! 489: } ! 490: break; ! 491: ! 492: case TTEMP: ! 493: if (p->tempblock.istemp) ! 494: frtemp(p); ! 495: break; ! 496: ! 497: default: ! 498: break; ! 499: } ! 500: return ((expptr) p); ! 501: } ! 502: ! 503: ! 504: ! 505: /* ! 506: * local version of routine putcat in putpcc.c, called by expand ! 507: */ ! 508: ! 509: LOCAL buffcat(lhs, rhs) ! 510: register Addrp lhs; ! 511: register expptr rhs; ! 512: { ! 513: int n; ! 514: Addrp lp, cp; ! 515: ! 516: n = ncat(rhs); ! 517: lp = (Addrp) mkaltmpn(n, TYLENG, PNULL); ! 518: cp = (Addrp) mkaltmpn(n, TYADDR, PNULL); ! 519: ! 520: n = 0; ! 521: buffct1(rhs, lp, cp, &n); ! 522: ! 523: optbuff (SKCALL, call4(TYSUBR, "s_cat", lhs, cp, lp, mkconv(TYLONG, ICON(n))), ! 524: 0, 0); ! 525: } ! 526: ! 527: ! 528: ! 529: /* ! 530: * local version of routine putct1 in putpcc.c, called by expand ! 531: */ ! 532: ! 533: LOCAL buffct1(q, lp, cp, ip) ! 534: register expptr q; ! 535: register Addrp lp, cp; ! 536: int *ip; ! 537: { ! 538: int i; ! 539: Addrp lp1, cp1; ! 540: ! 541: if(q->tag==TEXPR && q->exprblock.opcode==OPCONCAT) ! 542: { ! 543: buffct1(q->exprblock.leftp, lp, cp, ip); ! 544: buffct1(q->exprblock.rightp, lp, cp, ip); ! 545: frexpr(q->exprblock.vleng); ! 546: free( (charptr) q ); ! 547: } ! 548: else ! 549: { ! 550: i = (*ip)++; ! 551: lp1 = (Addrp) cpexpr(lp); ! 552: lp1->memoffset = mkexpr(OPPLUS,lp1->memoffset, ICON(i*SZLENG)); ! 553: cp1 = (Addrp) cpexpr(cp); ! 554: cp1->memoffset = mkexpr(OPPLUS, cp1->memoffset, ICON(i*SZADDR)); ! 555: optbuff (SKEQ, (mkexpr(OPASSIGN, lp1, cpexpr(q->headblock.vleng))), ! 556: 0,0); ! 557: optbuff (SKEQ, (mkexpr(OPASSIGN, cp1, addrof(expand (q)))), 0, 0); ! 558: } ! 559: } ! 560: ! 561: ! 562: ! 563: /* ! 564: * local version of routine putmnmx in putpcc.c, called by expand ! 565: */ ! 566: ! 567: LOCAL Addrp buffmnmx(p) ! 568: register expptr p; ! 569: { ! 570: int op, type; ! 571: expptr qp; ! 572: chainp p0, p1; ! 573: Addrp sp, tp; ! 574: Addrp newtemp; ! 575: expptr result, res; ! 576: ! 577: if(p->tag != TEXPR) ! 578: badtag("buffmnmx", p->tag); ! 579: ! 580: type = p->exprblock.vtype; ! 581: op = (p->exprblock.opcode==OPMIN ? OPLT : OPGT ); ! 582: p0 = p->exprblock.leftp->listblock.listp; ! 583: free( (charptr) (p->exprblock.leftp) ); ! 584: free( (charptr) p ); ! 585: ! 586: sp = mktemp(type, PNULL); ! 587: tp = mktemp(type, PNULL); ! 588: qp = mkexpr(OPCOLON, cpexpr(tp), cpexpr(sp)); ! 589: qp = mkexpr(OPQUEST, mkexpr(op, cpexpr(tp),cpexpr(sp)), qp); ! 590: qp = fixexpr(qp); ! 591: ! 592: newtemp = mktemp (type,PNULL); ! 593: ! 594: result = res = mkexpr (OPCOMMA, ! 595: mkexpr( OPASSIGN, cpexpr(sp), p0->datap ), cpexpr(newtemp)); ! 596: ! 597: for(p1 = p0->nextp ; p1 ; p1 = p1->nextp) ! 598: { ! 599: APPEND (mkexpr( OPASSIGN, cpexpr(tp), p1->datap )); ! 600: if(p1->nextp) ! 601: APPEND (mkexpr (OPASSIGN, cpexpr(sp), cpexpr(qp)) ); ! 602: else ! 603: APPEND (mkexpr (OPASSIGN, cpexpr(newtemp), qp)); ! 604: } ! 605: ! 606: frtemp(sp); ! 607: frtemp(tp); ! 608: frtemp(newtemp); ! 609: frchain( &p0 ); ! 610: ! 611: return ( (Addrp) result); ! 612: } ! 613: ! 614: ! 615: ! 616: /* ! 617: * Local version of putpower routine from putpcc.c, used by expand(). ! 618: */ ! 619: ! 620: LOCAL Addrp buffpower (p) ! 621: expptr p; ! 622: { ! 623: expptr base; ! 624: Addrp t1, t2; ! 625: ftnint k; ! 626: int type; ! 627: Addrp newtemp; ! 628: expptr res,result; ! 629: ! 630: if(!ISICON(p->exprblock.rightp) || ! 631: (k = p->exprblock.rightp->constblock.const.ci)<2) ! 632: fatal("buffpower: bad call"); ! 633: base = p->exprblock.leftp; ! 634: ! 635: if (k == 2) ! 636: { ! 637: expptr prod; ! 638: prod = mkexpr (OPSTAR,cpexpr(base),cpexpr(base)); ! 639: return ( (Addrp) prod); ! 640: } ! 641: ! 642: type = base->headblock.vtype; ! 643: newtemp = mktemp (type, PNULL); ! 644: ! 645: t1 = mktemp(type, PNULL); ! 646: t2 = NULL; ! 647: result = res = ! 648: mkexpr (OPCOMMA, mkexpr (OPASSIGN,cpexpr(t1),cpexpr(base)), ! 649: cpexpr (newtemp)); ! 650: ! 651: for( ; (k&1)==0 && k>2 ; k>>=1 ) ! 652: APPEND (mkexpr (OPSTAREQ,cpexpr(t1),cpexpr(t1))); ! 653: ! 654: if(k == 2) ! 655: { ! 656: expptr prod; ! 657: prod = mkexpr(OPSTAR, cpexpr(t1), cpexpr(t1)); ! 658: APPEND (mkexpr (OPASSIGN,cpexpr(newtemp),cpexpr(prod))); ! 659: } ! 660: else ! 661: { ! 662: t2 = mktemp(type, PNULL); ! 663: APPEND (mkexpr (OPASSIGN,cpexpr(t2),cpexpr(t1))); ! 664: ! 665: for(k>>=1 ; k>1 ; k>>=1) ! 666: { ! 667: APPEND (mkexpr (OPSTAREQ,cpexpr(t1),cpexpr(t1))); ! 668: if(k & 1) ! 669: APPEND (mkexpr (OPSTAREQ,cpexpr(t2),cpexpr(t1))); ! 670: } ! 671: APPEND (mkexpr (OPASSIGN, cpexpr(newtemp), mkexpr(OPSTAR, cpexpr(t2), ! 672: mkexpr(OPSTAR, cpexpr(t1), cpexpr(t1)) ))); ! 673: } ! 674: frexpr(t1); ! 675: if(t2) ! 676: frexpr(t2); ! 677: frexpr(p); ! 678: ! 679: return ( (Addrp) result); ! 680: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.