|
|
1.1 ! root 1: #include "gencode.h" ! 2: #define NDNUM 800 ! 3: mnod myt[NDNUM]; ! 4: extern mnod *svq; ! 5: int ntree; ! 6: char *regnames[] = {"r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", ! 7: "r9", "r10", "r11", "r12", "r13", "r14", "r15"}; ! 8: char *frameptr = "fp"; ! 9: char *argptr = "ap"; ! 10: #define CHARCHAR 'b' ! 11: #define SHORTCHAR 'w' ! 12: #define LONGCHAR 'l' ! 13: #define FLOATCHAR 'f' ! 14: #define DOUBLECHAR 'd' ! 15: ! 16: mnod * ! 17: gimmemnod() ! 18: { mnod *p; ! 19: p = myt + ntree++; ! 20: if(ntree > NDNUM) ! 21: cerror("out of temporary trees"); ! 22: return(p); ! 23: } ! 24: ! 25: mnod * ! 26: tempnode(p, flag) ! 27: mnod *p; ! 28: { mnod *x, *q; ! 29: int n; ! 30: extern int minrvar; ! 31: if(p->op == Conv) ! 32: q = p; /* Conv to double of float, versus (CMP double double) */ ! 33: else ! 34: q = (flag & RIGHT)? p->right: p->left; ! 35: x = gimmemnod(); ! 36: x->type = q->type; ! 37: n = incrsize(q) == 8? 2: 1; ! 38: if(!(flag & ASADDR) && regvar >= REGVAR - 1 + n) { ! 39: x->op = Reg; ! 40: x->rval = regvar + 1 - n; ! 41: x->lval = 1; /* SCRATCH marker !!!!! */ ! 42: regvar -= n; ! 43: if(minrvar > regvar) ! 44: minrvar = regvar; /* in case current routine recursive */ ! 45: return(x); ! 46: } ! 47: x->op = Auto; ! 48: x->lval = gimmetemp(n); ! 49: /* scratch marker? */ ! 50: return(x); ! 51: } ! 52: ret ! 53: alloctmp(p) ! 54: mnod *p; ! 55: { ret s; ! 56: sprintf(buf, "%d(%s)", gimmetemp(incrsize(p) == 8? 2: 1), frameptr); ! 57: done(s, CANINDIR|SCRATCH, 0); ! 58: } ! 59: ! 60: ret ! 61: allocreg(p, regmask) ! 62: mnod *p; ! 63: { int i, n; ! 64: ret s; ! 65: mnod *x; ! 66: if(p->type == Tdouble) ! 67: n = 2; ! 68: else ! 69: n = 1; ! 70: for(i = 0; i < REGVAR; i++) { ! 71: if(!(regmask & (1 << i))) ! 72: continue; ! 73: if(n == 2 & !(regmask & (1 << (1+i)))) ! 74: continue; ! 75: sprintx(buf, "%s", regnames[i]); ! 76: regmask = (1 << i); ! 77: if(n == 2) ! 78: regmask |= (1 << (i+1)); ! 79: done(s, SCRATCH|ISREG, regmask); ! 80: } ! 81: x = tempnode(p, 0); ! 82: if(x->op == Reg) { ! 83: sprintx(buf, "%s", regnames[x->rval]); ! 84: done(s, SCRATCH|ISREG, 0); ! 85: } ! 86: sprintx(buf, "%d(%s)", x->lval, frameptr); ! 87: done(s, SCRATCH|CANINDIR, 0); ! 88: } ! 89: ! 90: isfloat(p) ! 91: mnod *p; ! 92: { ! 93: return(p->type == Tfloat || p->type == Tdouble); ! 94: } ! 95: ! 96: childtype(p) ! 97: mnod *p; ! 98: { ! 99: return(type(p->left)); ! 100: } ! 101: ! 102: char typearr[] = {LONGCHAR, CHARCHAR, CHARCHAR, SHORTCHAR, SHORTCHAR, ! 103: LONGCHAR, LONGCHAR, LONGCHAR, LONGCHAR, ! 104: FLOATCHAR, DOUBLECHAR, '?', '?'}; ! 105: type(p) ! 106: mnod *p; ! 107: { ! 108: return(typearr[p->type]); ! 109: } ! 110: ! 111: int shiftarr[] = {2, 0, 0, 1, 1, 2, 2, 2, 2, 2, 3, -99, 0}; ! 112: shiftsize(p) ! 113: mnod *p; ! 114: { ! 115: return(shiftarr[p->type]); ! 116: } ! 117: ! 118: int incrarr[] = {4, 1, 1, 2, 2, 4, 4, 4, 4, 4, 8, -99, 0}; ! 119: incrsize(p) ! 120: mnod *p; ! 121: { ! 122: return(incrarr[p->type]); ! 123: } ! 124: ! 125: int unsarr[] = {1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0}; ! 126: isunsigned(p) ! 127: mnod *p; ! 128: { ! 129: return(unsarr[p->type]); ! 130: } ! 131: ! 132: mnod * ! 133: copymnod(p) ! 134: mnod *p; ! 135: { mnod *a, *b, *c; ! 136: c = gimmemnod(); ! 137: switch(p->op) { ! 138: case Andeq: case And: case Cmp: case Comop: case Decr: ! 139: case Diveq: case Div: case Xoreq: case Xor: ! 140: case Incr: case Lseq: case Ls: case Minuseq: case Minus: ! 141: case Modeq: case Mod: case Muleq: case Mul: case Oreq: ! 142: case Or: case Pluseq: case Plus: case Rseq: case Rs: ! 143: case Asg: case Cm: ! 144: case Call: case Stcall: ! 145: case Stasg: ! 146: a = copymnod(p->left); ! 147: b = copymnod(p->right); ! 148: *c = *p; ! 149: c->left = a; ! 150: c->right = b; ! 151: return(c); ! 152: case Compl: case Conv: case Genbr: case Genlab: ! 153: case Genubr: case Star: case Addr: case Ucall: ! 154: case Uminus: case Ustcall: case Init: case Funarg: ! 155: case Fld:case Starg: ! 156: a = copymnod(p->left); ! 157: *c = *p; ! 158: c->left = a; ! 159: return(c); ! 160: case Auto: case Reg: case Name: case Param: case Icon: ! 161: case Snode: case Rnode: case Qnode: ! 162: *c = *p; ! 163: return(c); ! 164: default: ! 165: cerror("unk mnod in copymnod"); ! 166: } ! 167: } ! 168: ! 169: /* rewrit A op B into (T = A, T) op B or A op (T = B, T) */ ! 170: totemp(p, flag) ! 171: mnod *p; ! 172: { mnod *a, *b, *c; ! 173: a = gimmemnod(); ! 174: b = tempnode(p, flag); ! 175: c = gimmemnod(); ! 176: if(flag & LEFT) ! 177: *a = *p->left; ! 178: else ! 179: *a = *p->right; ! 180: a->op = Asg; ! 181: a->left = b; ! 182: if(flag & LEFT) ! 183: a->right = p->left; ! 184: else ! 185: a->right = p->right; ! 186: c->op = Comop; ! 187: c->left = a; ! 188: c->right = b; ! 189: c->type = a->type; ! 190: if(flag & LEFT) ! 191: p->left = c; ! 192: else ! 193: p->right = c; ! 194: } ! 195: ! 196: funargs(p, regmask) ! 197: mnod *p; ! 198: { ret s, t; ! 199: int i; ! 200: switch(p->op) { ! 201: case Cm: /* order depends on way stack grows */ ! 202: #ifdef LTORARGS ! 203: i = funargs(p->left, regmask); ! 204: i |= funargs(p->right, regmask); ! 205: #else ! 206: i = funargs(p->right, regmask); ! 207: i |= funargs(p->left, regmask); ! 208: #endif ! 209: return(i); ! 210: case Funarg: ! 211: t = tostack(); ! 212: s = doit(p->left, VALUE|TOSTACK, t, regmask); ! 213: return(s.flag & FAIL); ! 214: case Starg: ! 215: /* this has to have same cases as STASG */ ! 216: if(regmask != REGMASK) ! 217: return(FAILX); ! 218: s = doit(p->left, (ASADDR|VALUE|FSTASG), 0, regmask); ! 219: /* this generates expensive code for small structures */ ! 220: i = p->stsize / 8; ! 221: if(p->left->op == Stasg) { ! 222: if(i != 4 && i != 8) { ! 223: pr("#\tsubl2\t$%d,sp\n", i); ! 224: pr("#\tsubl2\t$%d,r3\n", i); ! 225: pr("#\tmovc3\t$%d,(r3),(sp)\n", p->stsize/8); ! 226: return(0); ! 227: } ! 228: } ! 229: if(i == 4) ! 230: pr("#\tpushl\t%s\n", str(s)); ! 231: else if(i == 8) ! 232: pr("#\tmovq\t%s,-(sp)\n", str(s)); ! 233: else { ! 234: pr("#\tsubl2\t$%d,sp\n", i); ! 235: pr("#\tmovc3\t$%d,%s,(sp)\n", p->stsize/8, str(s)); ! 236: } ! 237: return(s.flag & FAIL); ! 238: } ! 239: } ! 240: ret ! 241: specialreg(p, regmask) ! 242: mnod *p; ! 243: { ret s; ! 244: int n, i; ! 245: n = p->type == Tdouble? 2: 1; ! 246: i = 1; ! 247: if(n == 2) ! 248: i = 3; ! 249: sprintx(buf, "%s", regnames[0]); ! 250: if(i & ~regmask) ! 251: pr("#\specialreg not free\n"); ! 252: done(s, SCRATCH|ISREG, i); ! 253: } ! 254: /* these guys rewrite a1 = a2 = ... an = x ! 255: * as t = x; an = t; an-1 = an */ ! 256: mnod * ! 257: fromtemp(p, temp) ! 258: mnod *p, *temp; ! 259: { mnod *q; ! 260: q = gimmemnod(); ! 261: *q = *p; ! 262: q->left = p; ! 263: q->op = Asg; ! 264: q->right = temp; ! 265: return(q); ! 266: } ! 267: ! 268: mnod * ! 269: to(p, temp) ! 270: mnod *p, *temp; ! 271: { mnod *q; ! 272: q = gimmemnod(); ! 273: *q = *p; ! 274: q->right = p; ! 275: q->op = Asg; ! 276: q->left = temp; ! 277: return(q); ! 278: } ! 279: ! 280: mnod * ! 281: commnod(a, p) ! 282: mnod *a, *p; ! 283: { mnod *q; ! 284: q = gimmemnod(); ! 285: *q = *p; ! 286: q->op = Comop; ! 287: q->right = p; ! 288: q->left = a; ! 289: return(q); ! 290: } ! 291: ! 292: asgwrite(p) ! 293: mnod *p; ! 294: { mnod *q, *a, *temp; ! 295: debugpr("#REWRITEasgwrite "); ! 296: temp = tempnode(p, 0); ! 297: a = fromtemp(p->left, temp); ! 298: for(q = p->right; q->op == Asg; q = q->right) ! 299: a = commnod(fromtemp(q->left, temp), a); ! 300: a = commnod(to(q, temp), a); ! 301: *p = *a; ! 302: } ! 303: ! 304: lsconv(p) ! 305: mnod *p; ! 306: { mnod *lft, *right; ! 307: debugpr("#REWRITElsconv "); ! 308: lft = gimmemnod(); ! 309: right = gimmemnod(); ! 310: lft->op = right->op = Conv; ! 311: lft->type = right->type = Tlong; ! 312: lft->left = p->left; ! 313: right->left = p->right; ! 314: if(p->left->op != Icon) /* Icon are longs anyway (see RS) */ ! 315: p->left = lft; ! 316: p->right = right; ! 317: } ! 318: /* only some ops have to be rewritten (addb and addl are the same at the bottom) */ ! 319: rewriteasgop(p) ! 320: mnod *p; ! 321: { mnod *a, *newop; ! 322: if(p->left->op != Conv) ! 323: return(0); ! 324: if(p->left->left->op == Star) ! 325: longjmp(back, awfulstar(p)); ! 326: debugpr("#REWRITE rewriteasgop "); ! 327: newop = gimmemnod(); ! 328: *newop = *p; ! 329: switch(p->op) { ! 330: case Diveq: ! 331: newop->op = Div; ! 332: break; ! 333: case Lseq: ! 334: newop->op = Ls; ! 335: break; ! 336: case Modeq: ! 337: newop->op = Mod; ! 338: break; ! 339: case Rseq: ! 340: newop->op = Rs; ! 341: break; ! 342: case Pluseq: ! 343: if(!isfloat(p->left)) ! 344: return(0); ! 345: newop->op = Plus; ! 346: break; ! 347: case Minuseq: ! 348: if(!isfloat(p->left)) ! 349: return(0); ! 350: newop->op = Minus; ! 351: break; ! 352: case Muleq: ! 353: if(!isfloat(p->left)) ! 354: return(0); ! 355: newop->op = Mul; ! 356: break; ! 357: ! 358: default: ! 359: cerror("codegen: rewriting asgop"); ! 360: } ! 361: a = gimmemnod(); ! 362: *a = *p->left->left; ! 363: p->op = Asg; ! 364: p->left = a; ! 365: p->right = newop; ! 366: return(1); ! 367: } ! 368: ! 369: rewriteconv(p) /* uns to float or double */ ! 370: mnod *p; ! 371: { mnod *a; ! 372: debugpr("#REWRITEconv "); ! 373: a = gimmemnod(); ! 374: *a = *p; ! 375: a->type = Tlong; ! 376: p->left = a; ! 377: } ! 378: ! 379: /* =(FLD(*(A)),B) -> ,(=(T,A), =(FLD(*(T)),B) */ ! 380: fldstar(p) ! 381: mnod *p; ! 382: { mnod *A, *B, *T, *newtop; ! 383: debugpr("#REWRITE fldstar ");write(2, "fldstar\n", 8); ! 384: A = p->left->left->left; ! 385: B = p->right; ! 386: T = tempnode(A, 0); ! 387: newtop = gimmemnod(); ! 388: newtop->op = Comop; ! 389: newtop->type = p->type; ! 390: newtop->left = gimmemnod(); ! 391: newtop->left->op = Asg; ! 392: newtop->left->type = A->type; ! 393: newtop->left->left = T; ! 394: newtop->left->right = A; ! 395: newtop->right = gimmemnod(); ! 396: *newtop->right = *p; ! 397: p->left->left->left = T; ! 398: *p = *newtop; ! 399: } ! 400: ! 401: mediumstar(p) ! 402: mnod *p; ! 403: { mnod *newtop, *tmp, *x, *y; ! 404: debugpr("#REWRITE mediumstar "); ! 405: newtop = gimmemnod(); ! 406: newtop->op = Comop; ! 407: newtop->type = p->type; ! 408: x = gimmemnod(); ! 409: x->op = Asg; ! 410: x->type = Tpoint; ! 411: x->right = p->left->left; ! 412: newtop->left = x; ! 413: tmp = tempnode(newtop, 0); ! 414: tmp->type = Tpoint; ! 415: x->left = tmp; ! 416: y = gimmemnod(); ! 417: y->op = Comop; ! 418: y->type = p->type; ! 419: x = gimmemnod(); ! 420: *x = *p; ! 421: newtop->right = y; ! 422: y->left = x; ! 423: y->right = x->left; ! 424: x->left->left = tmp; ! 425: *p = *newtop; ! 426: return(1); ! 427: } ! 428: ! 429: awfulstar(p) ! 430: mnod *p; ! 431: { mnod *newtop, *doleft, *x, *op, *equals; ! 432: debugpr("#REWRITE awfulstar "); ! 433: newtop = gimmemnod(); ! 434: newtop->op = Comop; ! 435: newtop->type = p->type; ! 436: doleft = gimmemnod(); ! 437: doleft->op = Asg; ! 438: doleft->type = Tpoint; ! 439: doleft->right = p->left->left->left; ! 440: x = tempnode(doleft, RIGHT); ! 441: doleft->left = x; ! 442: op = gimmemnod(); ! 443: *op = *p; ! 444: op->op += 1; /* cheap hack */ ! 445: op->left->left->left = x; /* so it's a dag, but x is harmless */ ! 446: equals = gimmemnod(); ! 447: *equals = *p; ! 448: equals->right = op; ! 449: equals->left = p->left->left; ! 450: equals->op = Asg; ! 451: *p = *newtop; ! 452: p->left = doleft; ! 453: p->right = equals; ! 454: return(1); ! 455: } ! 456: rewritefld(p) ! 457: mnod *p; ! 458: { mnod *q, *tmp, *left, *comop; ! 459: debugpr("#REWRITEfld "); ! 460: if((q = p->left->left)->op != Star) { ! 461: rewfld(p); ! 462: return; ! 463: } ! 464: q = q->left; ! 465: tmp = tempnode(q, 0); ! 466: left = gimmemnod(); ! 467: left->type = q->type; ! 468: left->op = Asg; ! 469: left->left = tmp; ! 470: left->right = gimmemnod(); ! 471: left->right = copymnod(q); ! 472: *q = *tmp; ! 473: comop = gimmemnod(); ! 474: comop->op = Comop; ! 475: comop->left = left; ! 476: comop->right = copymnod(p); ! 477: *p = *comop; ! 478: rewfld(p->right); ! 479: longjmp(back, 1); ! 480: } ! 481: rewfld(p) ! 482: mnod *p; ! 483: { mnod *x, *y, *z; ! 484: x = gimmemnod(); ! 485: *x = *copymnod(p); ! 486: y = gimmemnod(); ! 487: *y = *copymnod(p); ! 488: z = gimmemnod(); ! 489: *z = *p; ! 490: z->left = x; ! 491: x->op = Asg; ! 492: x->right = y; ! 493: if(p->op == Decr || p->op == Minuseq) ! 494: z->op = Plus; ! 495: else ! 496: z->op = Minus; ! 497: if(p->op == Decr) ! 498: y->op = Minus; ! 499: else if(p->op == Incr) ! 500: y->op = Plus; ! 501: else ! 502: y->op += 1; /* cheap hack */ ! 503: if(p->op == Decr || p->op == Incr) ! 504: *p = *z; ! 505: else ! 506: *p = *x; ! 507: } ! 508: /* not int = (...? int exprs) have a bogus tree */ ! 509: extracheck(p) ! 510: mnod *p; ! 511: { mnod *a; ! 512: if(p->right->op != Genlab && p->right->op != Comop) ! 513: return; ! 514: debugpr("#REWRITE extracheck "); ! 515: a = gimmemnod(); ! 516: *a = *p; ! 517: a->left = p->right; ! 518: a->op = Conv; ! 519: p->right = a; ! 520: } ! 521: ! 522: starasg(p) ! 523: mnod *p; ! 524: { mnod *tmp, *asg, *x; ! 525: debugpr("#REWRITE starasg "); ! 526: tmp = tempnode(p->left->left, 0); ! 527: x = gimmemnod(); ! 528: *x = *p; ! 529: asg = gimmemnod(); ! 530: *asg = *p->left->left; ! 531: asg->op = Asg; ! 532: asg->left = tmp; ! 533: asg->right = p->left->left; ! 534: x->left->left = tmp; ! 535: p->op = Comop; ! 536: p->left = asg; ! 537: p->right = x; ! 538: } ! 539: /* *A op= B => (T=A, *T op= B) if T has Incr or Asg */ ! 540: fixuns(p) ! 541: mnod *p; ! 542: { mnod *tmp, *asg, *new; ! 543: if(!sideffects(p->left->left)) ! 544: return(0); ! 545: debugpr("#REWRITE fixuns"); ! 546: tmp = tempnode(p->left->left, 0); ! 547: asg = gimmemnod(); ! 548: asg->type = tmp->type; ! 549: asg->op = Asg; ! 550: asg->left = tmp; ! 551: asg->right = p->left->left; ! 552: new = gimmemnod(); ! 553: *new = *p; ! 554: new->left->left = tmp; ! 555: p->op = Comop; ! 556: p->left = asg; ! 557: p->right = new; ! 558: return(1); ! 559: } ! 560: ! 561: stasgrewrite(p) ! 562: mnod *p; ! 563: { mnod *qa, *qb, *n, *left, *right; ! 564: debugpr("#REWRITE starasgrewrite "); ! 565: totemp(p, RIGHT); ! 566: longjmp(back, 1); ! 567: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.