|
|
1.1 ! root 1: #include <u.h> ! 2: #include <libc.h> ! 3: #include <bio.h> ! 4: #include <ctype.h> ! 5: #define Extern extern ! 6: #include "parl.h" ! 7: #include "globl.h" ! 8: ! 9: void ! 10: gendata(Node *n) ! 11: { ! 12: Type *t; ! 13: Inst *i; ! 14: ulong s; ! 15: ! 16: if(n == ZeroN) ! 17: return; ! 18: ! 19: switch(n->type) { ! 20: default: ! 21: gendata(n->left); ! 22: gendata(n->right); ! 23: break; ! 24: ! 25: case OAGDECL: ! 26: case OUNDECL: ! 27: case OADTDECL: ! 28: case OSETDECL: ! 29: case OFUNC: ! 30: break; ! 31: ! 32: case ONAME: ! 33: switch(n->t->class) { ! 34: case Internal: ! 35: case Global: ! 36: iline = n->srcline; ! 37: t = n->t; ! 38: if(n->init) ! 39: doinit(n, t, n->init, 0); ! 40: ! 41: s = t->size; ! 42: if(s == 0) ! 43: break; ! 44: if(s & (Align_data-1)) ! 45: s += Align_data-(s&(Align_data-1)); ! 46: ! 47: i = ai(); ! 48: i->op = AGLOBL; ! 49: mkaddr(con(s), &i->dst, 0); ! 50: mkaddr(n, &i->src1, 0); ! 51: ilink(i); ! 52: break; ! 53: } ! 54: break; ! 55: } ! 56: } ! 57: ! 58: /* Load/store instructions by type ! 59: ! 60: TXXX TINT TUINT TSINT TSUINT TCHAR TFLOAT TIND ! 61: TCHAN TARY TAGG TUNI TFUNC TVOID ! 62: */ ! 63: int ostore[] ={ AGOK, AMOVW, AMOVW, AMOVH, AMOVH, AMOVB, AFMOVD, AMOVW, ! 64: AMOVW, AGOK, AGOK, AGOK, AGOK, AGOK }; ! 65: ! 66: int oload[] = { AGOK, AMOVW, AMOVW, AMOVH, AMOVHU,AMOVBU,AFMOVD, AMOVW, ! 67: AMOVW,AGOK, AGOK, AGOK, AGOK, AGOK }; ! 68: ! 69: void ! 70: load(Node *from, Node *to) ! 71: { ! 72: Node n1; ! 73: int op; ! 74: ! 75: op = oload[from->t->type]; ! 76: reg(&n1, from->t, to); ! 77: instruction(op, from, ZeroN, &n1); ! 78: assign(&n1, to); ! 79: regfree(&n1); ! 80: } ! 81: ! 82: void ! 83: store(Node *from, Node *to) ! 84: { ! 85: Node n1; ! 86: int op, t; ! 87: ! 88: op = ostore[to->t->type]; ! 89: ! 90: t = from->t->type; ! 91: ! 92: if(t != TFLOAT) ! 93: if(vconst(from) == 0) { ! 94: instruction(op, from, ZeroN, to); ! 95: return; ! 96: } ! 97: ! 98: if(t == to->t->type) ! 99: reg(&n1, to->t, from); ! 100: else ! 101: reg(&n1, to->t, ZeroN); ! 102: ! 103: assign(from, &n1); ! 104: instruction(op, &n1, ZeroN, to); ! 105: regfree(&n1); ! 106: } ! 107: ! 108: void ! 109: inttoflt(Node *s, Node *d) ! 110: { ! 111: Inst *nofix; ! 112: Node n, *tmp; ! 113: ! 114: reg(&n, d->t, d); ! 115: tmp = stknode(d->t); ! 116: instruction(AMOVW, s, ZeroN, tmp); ! 117: instruction(AFMOVD, tmp, ZeroN, &n); ! 118: instruction(AFMOVWD, &n, ZeroN, d); ! 119: regfree(&n); ! 120: if(s->t->type == TUINT) { ! 121: instruction(ACMP, s, ZeroN, con(0)); ! 122: instruction(ABGE, ZeroN, ZeroN, ZeroN); ! 123: nofix = ipc; ! 124: reg(&n, builtype[TFLOAT], ZeroN); ! 125: instruction(AFMOVD, conf(4294967296.), ZeroN, &n); ! 126: instruction(AFADDD, &n, ZeroN, d); ! 127: regfree(&n); ! 128: label(nofix, ipc->pc+1); ! 129: } ! 130: } ! 131: ! 132: /* ! 133: * Compile code for moves ! 134: */ ! 135: void ! 136: assign(Node *src, Node *dst) ! 137: { ! 138: Node n1, *tmp; ! 139: int op, dt; ! 140: ! 141: if(opt('a')) ! 142: print("assign: %N = %N\n", dst, src); ! 143: ! 144: if(dst == ZeroN) ! 145: return; ! 146: ! 147: switch(src->type) { ! 148: case ONAME: ! 149: case OINDREG: ! 150: case OIND: ! 151: load(src, dst); ! 152: return; ! 153: } ! 154: ! 155: switch(dst->type) { ! 156: case ONAME: ! 157: case OINDREG: ! 158: case OIND: ! 159: store(src, dst); ! 160: return; ! 161: } ! 162: ! 163: /* delete register/register nop moves */ ! 164: if(src->type == OREGISTER) ! 165: if(dst->type == OREGISTER) ! 166: if(dst->reg == src->reg) ! 167: if(dst->type == src->type) ! 168: return; ! 169: ! 170: op = AGOK; ! 171: dt = dst->t->type; ! 172: switch(src->t->type) { ! 173: case TINT: ! 174: case TUINT: ! 175: case TIND: ! 176: case TCHANNEL: ! 177: switch(dt) { ! 178: case TINT: ! 179: case TUINT: ! 180: case TCHAR: ! 181: case TSUINT: ! 182: case TSINT: ! 183: case TIND: ! 184: case TCHANNEL: ! 185: op = AMOVW; ! 186: break; ! 187: ! 188: case TFLOAT: ! 189: inttoflt(src, dst); ! 190: return; ! 191: } ! 192: break; ! 193: ! 194: case TSUINT: ! 195: switch(dt) { ! 196: case TINT: ! 197: case TUINT: ! 198: case TIND: ! 199: op = AMOVHU; ! 200: break; ! 201: ! 202: case TSUINT: ! 203: case TCHAR: ! 204: case TSINT: ! 205: op = AMOVW; ! 206: break; ! 207: ! 208: case TFLOAT: ! 209: inttoflt(src, dst); ! 210: return; ! 211: } ! 212: break; ! 213: ! 214: case TSINT: ! 215: switch(dt) { ! 216: case TINT: ! 217: case TUINT: ! 218: case TIND: ! 219: op = AMOVH; ! 220: break; ! 221: ! 222: case TSUINT: ! 223: case TCHAR: ! 224: case TSINT: ! 225: op = AMOVW; ! 226: break; ! 227: ! 228: case TFLOAT: ! 229: inttoflt(src, dst); ! 230: return; ! 231: } ! 232: break; ! 233: ! 234: case TFLOAT: ! 235: switch(dt) { ! 236: case TINT: ! 237: case TUINT: ! 238: case TIND: ! 239: case TCHAR: ! 240: case TSINT: ! 241: case TSUINT: ! 242: reg(&n1, builtype[TFLOAT], ZeroN); ! 243: tmp = stknode(builtype[TINT]); ! 244: instruction(AFMOVDW, src, ZeroN, &n1); ! 245: instruction(AFMOVD, &n1, ZeroN, tmp); ! 246: regfree(&n1); ! 247: instruction(AMOVW, tmp, ZeroN, dst); ! 248: assign(dst, dst); ! 249: return; ! 250: ! 251: case TFLOAT: ! 252: op = AFMOVD; ! 253: break; ! 254: } ! 255: break; ! 256: case TCHAR: ! 257: switch(dt) { ! 258: case TINT: ! 259: case TUINT: ! 260: case TIND: ! 261: op = AMOVBU; ! 262: break; ! 263: ! 264: case TSUINT: ! 265: case TSINT: ! 266: case TCHAR: ! 267: op = AMOVW; ! 268: break; ! 269: ! 270: case TFLOAT: ! 271: inttoflt(src, dst); ! 272: return; ! 273: } ! 274: break; ! 275: } ! 276: instruction(op, src, ZeroN, dst); ! 277: } ! 278: ! 279: /* ! 280: * Generate the address of an expression ! 281: */ ! 282: void ! 283: genaddr(Node *expr, Node *dst) ! 284: { ! 285: Node n, *tmp; ! 286: ! 287: if(opt('g')) ! 288: print("genaddr: %N\n", expr); ! 289: ! 290: if(expr->type == OIND) { ! 291: genexp(expr->left, dst); ! 292: return; ! 293: } ! 294: if(isaddr(expr) == 0) { ! 295: tmp = stknode(expr->t); ! 296: n.type = OASGN; ! 297: n.t = tmp->t; ! 298: n.left = tmp; ! 299: n.right = expr; ! 300: n.islval = 0; ! 301: genexp(&n, ZeroN); ! 302: expr = tmp; ! 303: } ! 304: n = *expr; ! 305: reg(&n, builtype[TIND], dst); ! 306: n.type = OADDR; ! 307: n.left = expr; ! 308: n.right = ZeroN; ! 309: n.t = builtype[TIND]; ! 310: assign(&n, dst); ! 311: regfree(&n); ! 312: } ! 313: ! 314: /* ! 315: * generate an l-value into a register ! 316: */ ! 317: void ! 318: rgenaddr(Node *t, Node *rval, Node *lval) ! 319: { ! 320: Node *r; ! 321: ulong v; ! 322: ! 323: *t = *rval; ! 324: t->t = builtype[TIND]; ! 325: reg(t, t->t, lval); ! 326: if(rval->type == OIND) { ! 327: r = rval->left; ! 328: while(r->type == OADD) ! 329: r = r->right; ! 330: if(immed(r)) { ! 331: v = r->ival; ! 332: r->ival = 0; ! 333: genaddr(rval, t); ! 334: t->ival += v; ! 335: r->ival = v; ! 336: t->type = OINDREG; ! 337: t->t = rval->t; ! 338: return; ! 339: } ! 340: } ! 341: genaddr(rval, t); ! 342: t->type = OINDREG; ! 343: t->t = rval->t; ! 344: } ! 345: ! 346: /* ! 347: * pre and post increment generation ! 348: */ ! 349: void ! 350: postop(Node *rval, Node *lval) ! 351: { ! 352: Node *l, *nconst; ! 353: Node n1, n2, n3, n4; ! 354: ! 355: l = rval->left; ! 356: nconst = con(1); ! 357: if(l->t->type == TIND) ! 358: nconst->ival = l->t->next->size; ! 359: ! 360: if(rval->type == OPDEC) ! 361: nconst->ival = -nconst->ival; ! 362: ! 363: if(l->islval < Sucompute) ! 364: rgenaddr(&n2, l, ZeroN); ! 365: else ! 366: n2 = *l; ! 367: ! 368: n3.type = OADD; ! 369: n3.t = builtype[TINT]; ! 370: ! 371: /* Easy if we dont need the value after the inc */ ! 372: if(lval == ZeroN) { ! 373: reg(&n1, l->t, lval); ! 374: assign(&n2, &n1); ! 375: ! 376: codmop(&n3, nconst, &n1, &n1); ! 377: ! 378: assign(&n1, &n2); ! 379: goto out; ! 380: } ! 381: ! 382: reg(&n4, l->t, lval); ! 383: assign(&n2, &n4); ! 384: reg(&n1, l->t, ZeroN); ! 385: /* Thank RISC for three address ! */ ! 386: codmop(&n3, nconst, &n4, &n1); ! 387: assign(&n1, &n2); ! 388: ! 389: regfree(&n4); ! 390: out: ! 391: regfree(&n1); ! 392: if(l->islval < Sucompute) ! 393: regfree(&n2); ! 394: } ! 395: ! 396: void ! 397: preop(Node *rval, Node *lval) ! 398: { ! 399: Node n1, n2, n3; ! 400: Node *l, *nconst; ! 401: ! 402: l = rval->left; ! 403: nconst = con(1); ! 404: if(l->t->type == TIND) ! 405: nconst->ival = l->t->next->size; ! 406: ! 407: if(rval->type == OEDEC) ! 408: nconst->ival = -nconst->ival; ! 409: ! 410: if(l->islval < Sucompute) ! 411: rgenaddr(&n2, l, ZeroN); ! 412: else ! 413: n2 = *l; ! 414: ! 415: reg(&n1, l->t, lval); ! 416: assign(&n2, &n1); ! 417: ! 418: n3.type = OADD; ! 419: n3.t = builtype[TINT]; ! 420: codmop(&n3, nconst, &n1, &n1); ! 421: ! 422: assign(&n1, &n2); ! 423: ! 424: regfree(&n1); ! 425: if(l->islval < Sucompute) ! 426: regfree(&n2); ! 427: } ! 428: ! 429: void ! 430: docall(Node *n) ! 431: { ! 432: Node *rsp; ! 433: ! 434: if(atv == ZeroN) { ! 435: instruction(AJMPL, ZeroN, ZeroN, n); ! 436: return; ! 437: } ! 438: ! 439: /* ! 440: * if calling through an activation, link ! 441: * to the new stack ! 442: */ ! 443: ratv.ival = atv->atvsafe; ! 444: rsp = regn(RegSP); ! 445: instruction(AMOVW, rsp, ZeroN, &ratv); ! 446: ratv.type = OREGISTER; ! 447: assign(&ratv, rsp); ! 448: instruction(AJMPL, ZeroN, ZeroN, n); ! 449: rsp->type = OINDREG; ! 450: rsp->ival = atv->atvsafe; ! 451: instruction(AMOVW, rsp, ZeroN, regn(RegSP)); ! 452: regfree(&ratv); ! 453: } ! 454: ! 455: void ! 456: become(Node *rval) ! 457: { ! 458: Node nl; ! 459: Node *l, *r, *ns, *tmp; ! 460: ! 461: tmp = rval->left; ! 462: r = tmp->right; ! 463: l = tmp->left; ! 464: ! 465: if(opt('b')) { ! 466: print("BECOME:\n"); ! 467: ptree(rval, 0); ! 468: } ! 469: ! 470: tmp = ZeroN; ! 471: if(!isaddr(l)) { ! 472: tmp = stknode(builtype[TIND]); ! 473: genaddr(l, tmp); ! 474: } ! 475: ! 476: /* Generate the alias saves */ ! 477: genelist(rval->right); ! 478: ! 479: evalarg(r, 0); ! 480: ! 481: /* ! 482: * Write out tail recursion ! 483: */ ! 484: if(l->type == ONAME && curfunc->sym == l->sym) { ! 485: tip = block[Scope]; ! 486: evalarg(r, 4); ! 487: instruction(AJMP, ZeroN, ZeroN, ZeroN); ! 488: label(ipc, becomentry->pc+1); ! 489: return; ! 490: } ! 491: ! 492: ns = an(ONAME, ZeroN, ZeroN); ! 493: ns->sym = malloc(sizeof(Sym)); ! 494: ns->sym->name = ".xframe"; ! 495: ns->ti = ati(builtype[TADT], Parameter); ! 496: ns->ti->offset = 0; ! 497: ns->t = builtype[TINT]; ! 498: ns = an(OADDR, ns, nil); ! 499: sucalc(ns); ! 500: ! 501: reg(&ratv, builtype[TIND], ZeroN); ! 502: ratv.ival = Parambase; ! 503: genexp(ns, &ratv); ! 504: evalarg(r, 3); ! 505: regfree(&ratv); ! 506: ! 507: /* Restore the complex pointer */ ! 508: switch(curfunc->t->next->type) { ! 509: case TADT: ! 510: case TUNION: ! 511: case TAGGREGATE: ! 512: assign(rnode, regn(Regspass)); ! 513: break; ! 514: } ! 515: ! 516: if(tmp) { ! 517: reg(&nl, builtype[TIND], ZeroN); ! 518: assign(tmp, &nl); ! 519: nl.type = OINDREG; ! 520: nl.ival = 0; ! 521: instruction(ARETURN, con(ratv.ival), ZeroN, &nl); ! 522: regfree(&nl); ! 523: } ! 524: else ! 525: instruction(ARETURN, con(ratv.ival), ZeroN, l); ! 526: } ! 527: ! 528: /* ! 529: * Compile code expressions ! 530: */ ! 531: void ! 532: genexp(Node *rval, Node *lval) ! 533: { ! 534: Node nl, nr, nspare; ! 535: Node *l, *r, *nstack; ! 536: ! 537: l = rval->left; ! 538: r = rval->right; ! 539: ! 540: if(opt('v')) ! 541: print("%L R %N L %N\n", rval->srcline, rval, lval); ! 542: ! 543: if(rval->t) ! 544: switch(rval->t->type) { ! 545: case TADT: ! 546: case TUNION: ! 547: case TAGGREGATE: ! 548: gencomplex(rval, lval); ! 549: return; ! 550: } ! 551: ! 552: /* addressable */ ! 553: if(isaddr(rval)) { ! 554: assign(rval, lval); ! 555: return; ! 556: } ! 557: ! 558: /* Follow function call evaluations into stack temporary */ ! 559: if(rval->sun >= Sucall) ! 560: if(l->sun >= Sucall) ! 561: if(r && r->sun >= Sucall) ! 562: switch(rval->type) { ! 563: case OFUNC: ! 564: case OLAND: ! 565: case OLOR: ! 566: break; ! 567: ! 568: default: ! 569: regret(&nspare, r->t); ! 570: genexp(r, &nspare); ! 571: nstack = stknode(r->t); ! 572: assign(&nspare, nstack); ! 573: regfree(&nspare); ! 574: nspare = *rval; ! 575: nspare.right = nstack; ! 576: genexp(&nspare, lval); ! 577: return; ! 578: } ! 579: ! 580: switch(rval->type) { ! 581: default: ! 582: fatal("genexp: %N", rval); ! 583: break; ! 584: ! 585: case OBLOCK: ! 586: bstmnt(l); ! 587: genexp(r, lval); ! 588: break; ! 589: ! 590: case OBECOME: ! 591: become(rval); ! 592: break; ! 593: ! 594: case ODOT: ! 595: nstack = stknode(l->t); ! 596: genexp(l, nstack); ! 597: if(rval == ZeroN) ! 598: break; ! 599: ! 600: rgenaddr(&nspare, nstack, ZeroN); ! 601: nspare.ival = r->ival; ! 602: nspare.t = rval->t; ! 603: genexp(&nspare, lval); ! 604: regfree(&nspare); ! 605: break; ! 606: ! 607: case OCONV: ! 608: if(lval == ZeroN) { ! 609: warn(rval, "result ignored"); ! 610: break; ! 611: } ! 612: ! 613: if(convisnop(l->t, rval->t) && convisnop(rval->t, lval->t)) { ! 614: genexp(l, lval); ! 615: break; ! 616: } ! 617: reg(&nl, l->t, lval); ! 618: genexp(l, &nl); ! 619: reg(&nr, rval->t, &nl); ! 620: assign(&nl, &nr); ! 621: assign(&nr, lval); ! 622: regfree(&nr); ! 623: regfree(&nl); ! 624: break; ! 625: ! 626: case OASGN: ! 627: oasgn(rval, lval); ! 628: break; ! 629: ! 630: case OADDR: ! 631: if(lval == ZeroN) { ! 632: warn(rval, "result ignored"); ! 633: break; ! 634: } ! 635: ! 636: genaddr(l, lval); ! 637: break; ! 638: ! 639: case OIND: ! 640: if(lval == ZeroN) { ! 641: warn(rval, "result ignored"); ! 642: break; ! 643: } ! 644: reg(&nr, builtype[TIND], lval); ! 645: if(l->type == OADD && l->right->type == OCONST) { ! 646: nr.ival = l->right->ival; ! 647: genexp(l->left, &nr); ! 648: } ! 649: else { ! 650: genexp(l, &nr); ! 651: nr.ival = 0; ! 652: } ! 653: nr.type = OINDREG; ! 654: nr.t = rval->t; ! 655: assign(&nr, lval); ! 656: regfree(&nr); ! 657: break; ! 658: ! 659: case OCAND: ! 660: case OCOR: ! 661: case OEQ: ! 662: case OLEQ: ! 663: case ONEQ: ! 664: case OLT: ! 665: case OGEQ: ! 666: case OGT: ! 667: case OHI: ! 668: case OLO: ! 669: case OLOS: ! 670: case OHIS: ! 671: if(lval == ZeroN) ! 672: break; ! 673: ! 674: gencond(rval, lval, True); ! 675: break; ! 676: ! 677: case ONOT: ! 678: gencond(l, lval, False); ! 679: break; ! 680: ! 681: case OADDEQ: ! 682: case OSUBEQ: ! 683: case ORSHEQ: ! 684: case OLSHEQ: ! 685: case OANDEQ: ! 686: case OOREQ: ! 687: case OXOREQ: ! 688: while(l->type == OCONV) ! 689: l = l->left; ! 690: ! 691: /* Peel off the instructions with immediate operands */ ! 692: if(r->t->type != TFLOAT) ! 693: if(r->type == OCONST) { ! 694: if(l->islval < Sucompute) ! 695: rgenaddr(&nspare, l, ZeroN); ! 696: else ! 697: nspare = *l; ! 698: reg(&nl, r->t, lval); ! 699: assign(&nspare, &nl); ! 700: codmop(rval, r, &nl, &nl); ! 701: assign(&nl, &nspare); ! 702: ! 703: regfree(&nl); ! 704: if(l->islval < Sucompute) ! 705: regfree(&nspare); ! 706: break; ! 707: } ! 708: ! 709: /* Fall through */ ! 710: case OMULEQ: ! 711: case ODIVEQ: ! 712: case OMODEQ: ! 713: while(l->type == OCONV) ! 714: l = l->left; ! 715: ! 716: if(l->sun >= r->sun) { ! 717: if(l->islval < Sucompute) ! 718: rgenaddr(&nspare, l, ZeroN); ! 719: else ! 720: nspare = *l; ! 721: reg(&nr, r->t, ZeroN); ! 722: genexp(r, &nr); ! 723: } else { ! 724: reg(&nr, r->t, ZeroN); ! 725: genexp(r, &nr); ! 726: if(l->islval < Sucompute) ! 727: rgenaddr(&nspare, l, ZeroN); ! 728: else ! 729: nspare = *l; ! 730: } ! 731: ! 732: reg(&nl, rval->t, lval); ! 733: assign(&nspare, &nl); ! 734: codmop(rval, &nr, ZeroN, &nl); ! 735: assign(&nl, &nspare); ! 736: assign(&nl, lval); ! 737: regfree(&nl); ! 738: regfree(&nr); ! 739: if(l->islval < Sucompute) ! 740: regfree(&nspare); ! 741: break; ! 742: ! 743: case OADD: ! 744: case OSUB: ! 745: case OLAND: ! 746: case OLOR: ! 747: case OXOR: ! 748: case OLSH: ! 749: case ORSH: ! 750: case OALSH: ! 751: case OARSH: ! 752: if(lval == ZeroN) ! 753: break; ! 754: ! 755: /* Peel off the instructions with immediate operands */ ! 756: if(r->t->type != TFLOAT) ! 757: if(r->type == OCONST) { ! 758: genexp(l, lval); ! 759: if(r->ival == 0) ! 760: if(rval->type != OLAND) ! 761: break; ! 762: codmop(rval, r, lval, lval); ! 763: break; ! 764: } ! 765: ! 766: /* Fall through */ ! 767: case OMUL: ! 768: case ODIV: ! 769: case OMOD: ! 770: if(lval == ZeroN) { ! 771: warn(rval, "result ignored"); ! 772: break; ! 773: } ! 774: ! 775: if(rval->type == OMUL && mulcon(rval, lval)) ! 776: break; ! 777: ! 778: if(l->sun >= r->sun) { ! 779: reg(&nl, l->t, lval); ! 780: genexp(l, &nl); ! 781: reg(&nr, r->t, ZeroN); ! 782: genexp(r, &nr); ! 783: codmop(rval, &nr, &nl, &nl); ! 784: } ! 785: else { ! 786: reg(&nr, r->t, ZeroN); ! 787: genexp(r, &nr); ! 788: reg(&nl, l->t, lval); ! 789: genexp(l, &nl); ! 790: codmop(rval, &nr, &nl, &nl); ! 791: } ! 792: regfree(&nr); ! 793: assign(&nl, lval); ! 794: regfree(&nl); ! 795: break; ! 796: ! 797: case OPINC: ! 798: case OPDEC: ! 799: postop(rval, lval); ! 800: break; ! 801: ! 802: case OEINC: ! 803: case OEDEC: ! 804: preop(rval, lval); ! 805: break; ! 806: ! 807: case OSEND: ! 808: genexp(l, lval); ! 809: break; ! 810: ! 811: case ORECV: ! 812: case OCALL: ! 813: if(l->sun >= Sucall) { ! 814: reg(&nr, builtype[TIND], ZeroN); ! 815: genaddr(l, &nr); ! 816: if(nr.type != OREGISTER) ! 817: fatal("genexp: call %N", &nr); ! 818: ! 819: nstack = stknode(builtype[TIND]); ! 820: assign(&nr, nstack); ! 821: regfree(&nr); ! 822: ! 823: genarg(r); ! 824: ! 825: reg(&nr, builtype[TIND], ZeroN); ! 826: assign(nstack, &nr); ! 827: nr.type = OINDREG; ! 828: nr.ival = 0; ! 829: docall(&nr); ! 830: regfree(&nr); ! 831: break; ! 832: } ! 833: ! 834: genarg(r); ! 835: ! 836: if(!isaddr(l)) { ! 837: reg(&nr, builtype[TIND], ZeroN); ! 838: genaddr(l, &nr); ! 839: if(nr.type != OREGISTER) ! 840: fatal("genexp: call %N", &nr); ! 841: nr.type = OINDREG; ! 842: nr.ival = 0; ! 843: docall(&nr); ! 844: regfree(&nr); ! 845: } ! 846: else ! 847: docall(l); ! 848: ! 849: /* Return value */ ! 850: if(lval) { ! 851: regret(&nr, rval->t); ! 852: assign(&nr, lval); ! 853: regfree(&nr); ! 854: } ! 855: break; ! 856: ! 857: } ! 858: } ! 859: ! 860: /* ! 861: * Compile assignment operator ! 862: */ ! 863: void ! 864: oasgn(Node *rval, Node *lval) ! 865: { ! 866: Node n1, n2; ! 867: Node *l, *r; ! 868: ! 869: r = rval->right; ! 870: l = rval->left; ! 871: ! 872: if(opt('q')) { ! 873: print("OASGN r"); ! 874: ptree(rval, 0); ! 875: print("OASGN l"); ! 876: ptree(lval,0); ! 877: print("*\n"); ! 878: } ! 879: ! 880: if(l->islval >= Sucompute) ! 881: if(l->sun < Sucall) { ! 882: if(lval != ZeroN || r->islval < Sucompute) { ! 883: reg(&n1, r->t, lval); ! 884: genexp(r, &n1); ! 885: assign(&n1, l); ! 886: regfree(&n1); ! 887: } else ! 888: assign(r, l); ! 889: return; ! 890: } ! 891: ! 892: if(l->sun >= r->sun) { ! 893: rgenaddr(&n2, l, ZeroN); ! 894: if(r->islval >= Sucompute) { ! 895: assign(r, &n2); ! 896: assign(r, lval); ! 897: regfree(&n2); ! 898: return; ! 899: } ! 900: reg(&n1, r->t, lval); ! 901: genexp(r, &n1); ! 902: } else { ! 903: reg(&n1, r->t, lval); ! 904: genexp(r, &n1); ! 905: rgenaddr(&n2, l, ZeroN); ! 906: } ! 907: assign(&n1, &n2); ! 908: regfree(&n1); ! 909: regfree(&n2); ! 910: } ! 911: ! 912: void ! 913: evalarg(Node *n, int pass) ! 914: { ! 915: Node *tmp, n1; ! 916: ! 917: if(n == ZeroN) ! 918: return; ! 919: ! 920: switch(n->type) { ! 921: case OLIST: ! 922: evalarg(n->left, pass); ! 923: evalarg(n->right, pass); ! 924: break; ! 925: ! 926: default: ! 927: switch(pass) { ! 928: case 0: ! 929: if(n->type == OBLOCK) { ! 930: stmnt(n->left); ! 931: *n = *n->right; ! 932: break; ! 933: } ! 934: if(n->sun < Sucall) ! 935: break; ! 936: ! 937: tmp = stknode(n->t); ! 938: n1.type = OASGN; ! 939: n1.left = tmp; ! 940: n1.right = n; ! 941: n1.t = n->t; ! 942: sucalc(&n1); ! 943: genexp(&n1, ZeroN); ! 944: *n = *tmp; ! 945: break; ! 946: ! 947: case 1: ! 948: if(atv) ! 949: tmp = atvnode(n->t); ! 950: else ! 951: tmp = argnode(n->t); ! 952: compute: ! 953: switch(n->t->type) { ! 954: default: ! 955: fatal("evalarg %T", n->t); ! 956: case TADT: ! 957: case TUNION: ! 958: case TAGGREGATE: ! 959: gencomplex(n, tmp); ! 960: break; ! 961: ! 962: case TSINT: ! 963: case TSUINT: ! 964: case TCHAR: ! 965: case TINT: ! 966: case TUINT: ! 967: case TIND: ! 968: case TFLOAT: ! 969: case TCHANNEL: ! 970: n1.type = OASGN; ! 971: n1.left = tmp; ! 972: n1.right = n; ! 973: n1.t = n->t; ! 974: sucalc(&n1); ! 975: genexp(&n1, ZeroN); ! 976: break; ! 977: } ! 978: break; ! 979: case 3: ! 980: /* ! 981: * Second pass becoming somebody else ! 982: */ ! 983: tmp = atvnode(n->t); ! 984: if(n->type == ONAME) ! 985: if(n->ti->class == Parameter) ! 986: if(n->ti->offset == tmp->left->right->ival) ! 987: break; ! 988: goto compute; ! 989: case 4: ! 990: /* ! 991: * Second pass becoming myself ! 992: */ ! 993: tmp = paramnode(n->t); ! 994: if(tmp->type == ONAME) ! 995: if(tmp->sym == n->sym) ! 996: if(tmp->ti->class == n->ti->class) ! 997: break; ! 998: goto compute; ! 999: } ! 1000: } ! 1001: } ! 1002: ! 1003: /* ! 1004: * genarg - Push function arguments onto the stack ! 1005: */ ! 1006: void ! 1007: genarg(Node *n) ! 1008: { ! 1009: evalarg(n, 0); ! 1010: ! 1011: args = Argbase; ! 1012: if(atv) { ! 1013: reg(&ratv, builtype[TIND], 0); ! 1014: assign(atv, &ratv); ! 1015: ratv.type = OINDREG; ! 1016: ratv.ival = Argbase; ! 1017: evalarg(n, 1); ! 1018: return; ! 1019: } ! 1020: ! 1021: evalarg(n, 1); ! 1022: if(args > maxframe) ! 1023: maxframe = args; ! 1024: } ! 1025: ! 1026: /* ! 1027: * Compute the frame size of function arguments ! 1028: */ ! 1029: void ! 1030: framesize(Node *n) ! 1031: { ! 1032: if(n == ZeroN) ! 1033: return; ! 1034: ! 1035: switch(n->type) { ! 1036: case OLIST: ! 1037: framesize(n->left); ! 1038: framesize(n->right); ! 1039: break; ! 1040: ! 1041: default: ! 1042: frsize = align(frsize, builtype[TINT]); ! 1043: frsize += n->t->size; ! 1044: } ! 1045: } ! 1046: ! 1047: void ! 1048: setcond(Node *lval) ! 1049: { ! 1050: Inst *true, *false; ! 1051: ! 1052: if(lval == ZeroN) ! 1053: return; ! 1054: ! 1055: true = ipc; ! 1056: assign(con(1), lval); ! 1057: instruction(AJMP, ZeroN, ZeroN, ZeroN); ! 1058: false = ipc; ! 1059: label(true, ipc->pc+1); ! 1060: assign(con(0), lval); ! 1061: label(false, ipc->pc+1); ! 1062: } ! 1063: ! 1064: void ! 1065: andand(Node *l, Node *r, int bool) ! 1066: { ! 1067: Inst *true, *false; ! 1068: ! 1069: if(l->t == ZeroT) ! 1070: instruction(AJMP, ZeroN, ZeroN, ZeroN); ! 1071: else ! 1072: gencond(l, ZeroN, bool); ! 1073: ! 1074: false = ipc; ! 1075: ! 1076: if(r->t == ZeroT) ! 1077: instruction(AJMP, ZeroN, ZeroN, ZeroN); ! 1078: else ! 1079: gencond(r, ZeroN, !bool); ! 1080: ! 1081: true = ipc; ! 1082: ! 1083: label(false, ipc->pc+1); ! 1084: instruction(AJMP, ZeroN, ZeroN, ZeroN); ! 1085: label(true, ipc->pc+1); ! 1086: ! 1087: } ! 1088: ! 1089: void ! 1090: oror(Node *l, Node *r, int bool) ! 1091: { ! 1092: Inst *false1, *false2; ! 1093: ! 1094: if(l->t == ZeroT) ! 1095: instruction(AJMP, ZeroN, ZeroN, ZeroN); ! 1096: else ! 1097: gencond(l, ZeroN, !bool); ! 1098: ! 1099: false1 = ipc; ! 1100: ! 1101: if(r->t == ZeroT) ! 1102: instruction(AJMP, ZeroN, ZeroN, ZeroN); ! 1103: else ! 1104: gencond(r, ZeroN, !bool); ! 1105: ! 1106: false2 = ipc; ! 1107: ! 1108: instruction(AJMP, ZeroN, ZeroN, ZeroN); ! 1109: label(false1, ipc->pc+1); ! 1110: label(false2, ipc->pc+1); ! 1111: } ! 1112: ! 1113: /* ! 1114: * Generate for boolean conditionals ! 1115: */ ! 1116: void ! 1117: gencond(Node *rval, Node *lval, int bool) ! 1118: { ! 1119: int op; ! 1120: Node n1, n2; ! 1121: Node *l, *r, *nstack; ! 1122: ! 1123: l = rval->left; ! 1124: r = rval->right; ! 1125: ! 1126: op = rval->type; ! 1127: switch(op) { ! 1128: default: ! 1129: reg(&n1, rval->t, lval); ! 1130: genexp(rval, &n1); ! 1131: if(bool) ! 1132: op = OEQ; ! 1133: else ! 1134: op = ONEQ; ! 1135: codcond(op, &n1, con(0)); ! 1136: setcond(lval); ! 1137: regfree(&n1); ! 1138: return; ! 1139: ! 1140: case OCAND: ! 1141: if(bool == False) ! 1142: oror(l, r, bool); ! 1143: else ! 1144: andand(l, r, bool); ! 1145: break; ! 1146: ! 1147: case OCOR: ! 1148: if(bool == False) ! 1149: andand(l, r, bool); ! 1150: else ! 1151: oror(l, r, bool); ! 1152: break; ! 1153: ! 1154: case ONOT: ! 1155: gencond(rval->left, lval, !bool); ! 1156: break; ! 1157: ! 1158: case OHI: ! 1159: case OLO: ! 1160: case OLOS: ! 1161: case OHIS: ! 1162: case OEQ: ! 1163: case OLEQ: ! 1164: case ONEQ: ! 1165: case OLT: ! 1166: case OGEQ: ! 1167: case OGT: ! 1168: if(r->sun >= Sucall && l->sun >= Sucall) { ! 1169: nstack = stknode(l->t); ! 1170: genexp(l, nstack); ! 1171: rval->left = nstack; ! 1172: gencond(rval, lval, bool); ! 1173: return; ! 1174: } ! 1175: ! 1176: if(bool) ! 1177: op = not[op]; ! 1178: ! 1179: if(immed(r)) { ! 1180: reg(&n1, l->t, lval); ! 1181: genexp(l, &n1); ! 1182: codcond(op, &n1, r); ! 1183: regfree(&n1); ! 1184: setcond(lval); ! 1185: return; ! 1186: } ! 1187: if(l->sun >= r->sun) { ! 1188: reg(&n1, l->t, lval); ! 1189: genexp(l, &n1); ! 1190: reg(&n2, r->t, ZeroN); ! 1191: genexp(r, &n2); ! 1192: } ! 1193: else { ! 1194: reg(&n2, r->t, lval); ! 1195: genexp(r, &n2); ! 1196: reg(&n1, l->t, ZeroN); ! 1197: genexp(l, &n1); ! 1198: } ! 1199: codcond(op, &n1, &n2); ! 1200: regfree(&n1); ! 1201: regfree(&n2); ! 1202: } ! 1203: setcond(lval); ! 1204: } ! 1205: ! 1206: void ! 1207: genelist(Node *n) ! 1208: { ! 1209: if(n == ZeroN) ! 1210: return; ! 1211: ! 1212: switch(n->type) { ! 1213: case OLIST: ! 1214: genelist(n->left); ! 1215: genelist(n->right); ! 1216: break; ! 1217: default: ! 1218: genexp(n, ZeroN); ! 1219: break; ! 1220: } ! 1221: } ! 1222: ! 1223: void ! 1224: gensubreg(Node *n, Node *reg) ! 1225: { ! 1226: if(n == ZeroN) ! 1227: return; ! 1228: ! 1229: switch(n->type) { ! 1230: default: ! 1231: gensubreg(n->left, reg); ! 1232: gensubreg(n->right, reg); ! 1233: break; ! 1234: case OREGISTER: ! 1235: *n = *reg; ! 1236: break; ! 1237: } ! 1238: } ! 1239: ! 1240: void ! 1241: genmove(Node *rval, Type *rt, Node *lval, int o) ! 1242: { ! 1243: Type *t; ! 1244: Node *l, *r; ! 1245: ! 1246: for(t = rt->next; t; t = t->member) { ! 1247: switch(t->type) { ! 1248: case TFUNC: ! 1249: break; ! 1250: case TADT: ! 1251: case TAGGREGATE: ! 1252: genmove(rval, t, lval, t->offset); ! 1253: break; ! 1254: default: ! 1255: r = an(OADDR, rval, ZeroN); ! 1256: r->t = at(TIND, t); ! 1257: r = an(OADD, r, con(o+t->offset)); ! 1258: r->t = r->left->t; ! 1259: r = an(OIND, r, ZeroN); ! 1260: r->t = t; ! 1261: l = an(OADDR, lval, ZeroN); ! 1262: l->t = at(TIND, t); ! 1263: l = an(OADD, l, con(o+t->offset)); ! 1264: l->t = l->left->t; ! 1265: l = an(OIND, l, ZeroN); ! 1266: l->t = t; ! 1267: sucalc(r); ! 1268: sucalc(l); ! 1269: genexp(r, l); ! 1270: } ! 1271: } ! 1272: } ! 1273: ! 1274: int ! 1275: bitmove(Node *rval, Node *lval) ! 1276: { ! 1277: if(!isaddr(rval)) ! 1278: return 0; ! 1279: ! 1280: if(!isaddr(lval)) ! 1281: return 0; ! 1282: ! 1283: genmove(rval, rval->t, lval, 0); ! 1284: return 1; ! 1285: } ! 1286: ! 1287: /* ! 1288: * generate moves for complex types ! 1289: */ ! 1290: void ! 1291: gencomplex(Node *rval, Node *lval) ! 1292: { ! 1293: Type *t; ! 1294: Inst *back; ! 1295: int size, w, i, o; ! 1296: Node *l, *r, *tmp, *ptr; ! 1297: Node n1, n2, treg, loop; ! 1298: ! 1299: if(opt('x')) { ! 1300: print("GENCOM r\n"); ! 1301: ptree(rval, 0); ! 1302: print("*\nGENCOM l\n"); ! 1303: ptree(lval, 0); ! 1304: } ! 1305: ! 1306: r = rval->right; ! 1307: l = rval->left; ! 1308: ! 1309: switch(rval->type) { ! 1310: case OBLOCK: ! 1311: bstmnt(l); ! 1312: gencomplex(r, lval); ! 1313: break; ! 1314: ! 1315: case ODOT: ! 1316: tmp = stknode(l->t); ! 1317: genexp(l, tmp); ! 1318: if(rval == ZeroN) ! 1319: break; ! 1320: ! 1321: tmp->ival = r->ival; ! 1322: tmp->t = rval->t; ! 1323: genexp(tmp, lval); ! 1324: break; ! 1325: ! 1326: case OASGN: ! 1327: if(l->type == OILIST) { ! 1328: if(!isaddr(r) || lval != 0) { ! 1329: tmp = stknode(r->t); ! 1330: gencomplex(r, tmp); ! 1331: } ! 1332: else ! 1333: tmp = r; ! 1334: ! 1335: reg(&treg, builtype[TIND], ZeroN); ! 1336: genaddr(tmp, &treg); ! 1337: ptr = stknode(builtype[TIND]); ! 1338: assign(&treg, ptr); ! 1339: regfree(&treg); ! 1340: ! 1341: gensubreg(l->left, ptr); ! 1342: genelist(l->left); ! 1343: if(lval) ! 1344: gencomplex(tmp, lval); ! 1345: break; ! 1346: } ! 1347: if(lval == ZeroN) { ! 1348: if(rval->islval < Sucompute) ! 1349: gencomplex(r, l); ! 1350: break; ! 1351: } ! 1352: tmp = stknode(rval->t); ! 1353: gencomplex(r, tmp); ! 1354: gencomplex(tmp, l); ! 1355: gencomplex(tmp, lval); ! 1356: break; ! 1357: ! 1358: case ORECV: ! 1359: case OCALL: ! 1360: if(lval == ZeroN) { ! 1361: tmp = stknode(rval->t); ! 1362: gencomplex(rval, tmp); ! 1363: break; ! 1364: } ! 1365: ! 1366: if(l->sun >= Sucall) { ! 1367: reg(&treg, builtype[TIND], ZeroN); ! 1368: genaddr(l, &treg); ! 1369: if(treg.type != OREGISTER) ! 1370: fatal("gencomplex: call %N", &treg); ! 1371: ! 1372: l = stknode(builtype[TIND]); ! 1373: l = an(OIND, l, ZeroN); ! 1374: l->t = builtype[TIND]; ! 1375: assign(&treg, l); ! 1376: regfree(&treg); ! 1377: } ! 1378: genarg(r); ! 1379: ! 1380: t = at(TIND, lval->t); ! 1381: regret(&n1, t); ! 1382: if(isaddr(lval)) { ! 1383: lval = an(OADDR, lval, ZeroN); ! 1384: lval->t = t; ! 1385: genexp(lval, &n1); ! 1386: tmp = ZeroN; ! 1387: } ! 1388: else { ! 1389: tmp = stknode(lval->t); ! 1390: n2.type = OADDR; ! 1391: n2.ival = 0; ! 1392: n2.t = t; ! 1393: n2.left = tmp; ! 1394: n2.right = ZeroN; ! 1395: genexp(&n2, &n1); ! 1396: } ! 1397: ! 1398: if(!isaddr(l)) { ! 1399: reg(&treg, builtype[TIND], ZeroN); ! 1400: genaddr(l, &treg); ! 1401: if(treg.type != OREGISTER) ! 1402: fatal("gencomplex: call %N", &treg); ! 1403: ! 1404: treg.type = OINDREG; ! 1405: treg.ival = 0; ! 1406: docall(&treg); ! 1407: regfree(&treg); ! 1408: } ! 1409: else ! 1410: docall(l); ! 1411: ! 1412: regfree(&n1); ! 1413: ! 1414: if(tmp) ! 1415: gencomplex(tmp, lval); ! 1416: ! 1417: break; ! 1418: ! 1419: case OILIST: ! 1420: if(lval == ZeroN) { ! 1421: warn(rval, "result ignored"); ! 1422: break; ! 1423: } ! 1424: ! 1425: t = lval->t; ! 1426: lval->t = builtype[TINT]; ! 1427: rgenaddr(&n2, lval, ZeroN); ! 1428: if(t->type == TPOLY) ! 1429: lval->t = polyshape; ! 1430: else ! 1431: lval->t = t; ! 1432: o = n2.ival; ! 1433: n2.ival = 0; ! 1434: cominit(&n2, lval->t, rval, o); ! 1435: regfree(&n2); ! 1436: break; ! 1437: ! 1438: default: ! 1439: if(lval == ZeroN) { ! 1440: warn(rval, "result ignored"); ! 1441: break; ! 1442: } ! 1443: ! 1444: size = rval->t->size; ! 1445: w = builtype[TINT]->size; ! 1446: size /= w; ! 1447: if(size < 6 && notunion(rval->t) && bitmove(rval, lval)) ! 1448: break; ! 1449: ! 1450: if(rval->sun > lval->sun) { ! 1451: t = rval->t; ! 1452: rval->t = builtype[TINT]; ! 1453: rgenaddr(&n1, rval, ZeroN); ! 1454: rval->t = t; ! 1455: ! 1456: t = lval->t; ! 1457: lval->t = builtype[TINT]; ! 1458: rgenaddr(&n2, lval, ZeroN); ! 1459: lval->t = t; ! 1460: } ! 1461: else { ! 1462: t = lval->t; ! 1463: lval->t = builtype[TINT]; ! 1464: rgenaddr(&n2, lval, ZeroN); ! 1465: lval->t = t; ! 1466: ! 1467: t = rval->t; ! 1468: rval->t = builtype[TINT]; ! 1469: rgenaddr(&n1, rval, ZeroN); ! 1470: rval->t = t; ! 1471: } ! 1472: ! 1473: reg(&treg, builtype[TINT], ZeroN); ! 1474: if(size < 6) { ! 1475: for(i = 0; i < size; i++) { ! 1476: instruction(AMOVW, &n1, ZeroN, &treg); ! 1477: instruction(AMOVW, &treg, ZeroN, &n2); ! 1478: n1.ival += w; ! 1479: n2.ival += w; ! 1480: } ! 1481: } ! 1482: else { ! 1483: reg(&loop, builtype[TINT], ZeroN); ! 1484: ! 1485: instruction(AMOVW, con(size), ZeroN, &loop); ! 1486: instruction(AMOVW, &n1, ZeroN, &treg); ! 1487: back = ipc; ! 1488: instruction(AMOVW, &treg, ZeroN, &n2); ! 1489: n1.type = OREGISTER; ! 1490: n2.type = OREGISTER; ! 1491: instruction(AADD, con(w), ZeroN, &n1); ! 1492: instruction(AADD, con(w), ZeroN, &n2); ! 1493: instruction(ASUBCC, con(1), ZeroN, &loop); ! 1494: instruction(ABNE, ZeroN, ZeroN, ZeroN); ! 1495: label(ipc, back->pc); ! 1496: regfree(&loop); ! 1497: } ! 1498: regfree(&treg); ! 1499: regfree(&n1); ! 1500: regfree(&n2); ! 1501: } ! 1502: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.