1: static char sccsid[] = "@(#)c10.c 2.2"; /* SCCS id keyword */ 2: # 3: /* 4: 5: C compiler, part 2 6: 7: 8: */ 9: 10: #include "c1.h" 11: 12: #define dbprint(op) /* */ 13: #ifdef DEBUG 14: #define dbprint(op) printf(" / %s", opntab[op]) 15: #endif 16: 17: char maprel[] { EQUAL, NEQUAL, GREATEQ, GREAT, LESSEQ, 18: LESS, GREATQP, GREATP, LESSEQP, LESSP 19: }; 20: 21: char notrel[] { NEQUAL, EQUAL, GREAT, GREATEQ, LESS, 22: LESSEQ, GREATP, GREATQP, LESSP, LESSEQP 23: }; 24: 25: struct tconst czero { CON, INT, 0}; 26: struct tconst cone { CON, INT, 1}; 27: 28: struct tname sfuncr { NAME, STRUCT, STATIC, 0, 0, 0 }; 29: 30: struct table *cregtab; 31: 32: int nreg 3; 33: int isn 10000; 34: 35: main(argc, argv) 36: char *argv[]; 37: { 38: 39: if (argc<4) { 40: error("Arg count"); 41: exit(1); 42: } 43: if (freopen(argv[1], "r", stdin)==NULL) { 44: error("Missing temp file"); 45: exit(1); 46: } 47: if ((freopen(argv[3], "w", stdout)) == NULL) { 48: error("Can't create %s", argv[3]); 49: exit(1); 50: } 51: #ifdef MENLO_OVLY 52: if (argc > 4) 53: ovlyflag++; 54: #endif MENLO_OVLY 55: funcbase = curbase = coremax = sbrk(0); 56: getree(); 57: /* 58: * If any floating-point instructions 59: * were used, generate a reference that 60: * pulls in the floating-point part of printf. 61: */ 62: if (nfloat) 63: printf(".globl fltused\n"); 64: /* 65: * tack on the string file. 66: */ 67: printf(".globl\n.data\n"); 68: if (*argv[2] != '-') { 69: if (freopen(argv[2], "r", stdin)==NULL) { 70: error("Missing temp file"); 71: exit(1); 72: } 73: getree(); 74: } 75: if (totspace >= (unsigned)56000) { 76: error("Warning: possibly too much data"); 77: nerror--; 78: } 79: exit(nerror!=0); 80: } 81: 82: /* 83: * Given a tree, a code table, and a 84: * count of available registers, find the code table 85: * for the appropriate operator such that the operands 86: * are of the right type and the number of registers 87: * required is not too large. 88: * Return a ptr to the table entry or 0 if none found. 89: */ 90: char * 91: match(atree, table, nrleft, nocvt) 92: struct tnode *atree; 93: struct table *table; 94: { 95: #define NOCVL 1 96: #define NOCVR 2 97: int op, d1, d2, dope; 98: struct tnode *p2; 99: register struct tnode *p1, *tree; 100: register struct optab *opt; 101: 102: if ((tree=atree)==0) 103: return(0); 104: if (table==lsptab) 105: table = sptab; 106: if ((op = tree->op)==0) 107: return(0); 108: dope = opdope[op]; 109: if ((dope&LEAF) == 0) 110: p1 = tree->tr1; 111: else 112: p1 = tree; 113: d1 = dcalc(p1, nrleft); 114: if ((dope&BINARY)!=0) { 115: p2 = tree->tr2; 116: /* 117: * If a subtree starts off with a conversion operator, 118: * try for a match with the conversion eliminated. 119: * E.g. int = double can be done without generating 120: * the converted int in a register by 121: * movf double,fr0; movfi fr0,int . 122: */ 123: if (opdope[p2->op]&CNVRT && (nocvt&NOCVR)==0 124: && (opdope[p2->tr1->op]&CNVRT)==0) { 125: tree->tr2 = p2->tr1; 126: if (opt = match(tree, table, nrleft, NOCVL)) 127: return(opt); 128: tree->tr2 = p2; 129: } else if (opdope[p1->op]&CNVRT && (nocvt&NOCVL)==0 130: && (opdope[p1->tr1->op]&CNVRT)==0) { 131: tree->tr1 = p1->tr1; 132: if (opt = match(tree, table, nrleft, NOCVR)) 133: return(opt); 134: tree->tr1 = p1; 135: } 136: d2 = dcalc(p2, nrleft); 137: } 138: for (; table->op!=op; table++) 139: if (table->op==0) 140: return(0); 141: for (opt = table->tabp; opt->tabdeg1!=0; opt++) { 142: if (d1 > (opt->tabdeg1&077) 143: || (opt->tabdeg1 >= 0100 && (p1->op != STAR))) 144: continue; 145: if (notcompat(p1, opt->tabtyp1, op)) { 146: continue; 147: } 148: if ((opdope[op]&BINARY)!=0 && p2!=0) { 149: if (d2 > (opt->tabdeg2&077) 150: || (opt->tabdeg2 >= 0100) && (p2->op != STAR) ) 151: continue; 152: if (notcompat(p2,opt->tabtyp2, 0)) 153: continue; 154: } 155: return(opt); 156: } 157: return(0); 158: } 159: 160: /* 161: * Given a tree, a code table, and a register, 162: * produce code to evaluate the tree with the appropriate table. 163: * Registers reg and upcan be used. 164: * If there is a value, it is desired that it appear in reg. 165: * The routine returns the register in which the value actually appears. 166: * This routine must work or there is an error. 167: * If the table called for is cctab, sptab, or efftab, 168: * and tree can't be done using the called-for table, 169: * another try is made. 170: * If the tree can't be compiled using cctab, regtab is 171: * used and a "tst" instruction is produced. 172: * If the tree can't be compiled using sptab, 173: * regtab is used and the register is pushed on the stack. 174: * If the tree can't be compiled using efftab, 175: * just use regtab. 176: * Regtab must succeed or an "op not found" error results. 177: * 178: * A number of special cases are recognized, and 179: * there is an interaction with the optimizer routines. 180: */ 181: rcexpr(atree, atable, reg) 182: struct tnode *atree; 183: struct table *atable; 184: { 185: register r; 186: int modf, nargs, recurf; 187: register struct tnode *tree; 188: register struct table *table; 189: 190: table = atable; 191: recurf = 0; 192: if (reg<0) { 193: recurf++; 194: reg = ~reg; 195: if (reg>=020) { 196: reg =- 020; 197: recurf++; 198: } 199: } 200: again: 201: if((tree=atree)==0) 202: return(0); 203: if (opdope[tree->op]&RELAT && tree->tr2->op==CON && tree->tr2->value==0 204: && table==cctab) 205: tree = atree = tree->tr1; 206: /* 207: * fieldselect(...) : in efftab mode, 208: * ignore the select, otherwise 209: * do the shift and mask. 210: */ 211: if (tree->op == FSELT) { 212: if (table==efftab) 213: atree = tree = tree->tr1; 214: else { 215: tree->op = FSEL; 216: atree = tree = optim(tree); 217: } 218: } 219: switch (tree->op) { 220: 221: /* 222: * Structure assignments 223: */ 224: case STRASG: 225: strasg(tree); 226: return(0); 227: 228: /* 229: * An initializing expression 230: */ 231: case INIT: 232: tree = optim(tree); 233: doinit(tree->type, tree->tr1); 234: return(0); 235: 236: /* 237: * Put the value of an expression in r0, 238: * for a switch or a return 239: */ 240: case RFORCE: 241: tree = tree->tr1; 242: if((r=rcexpr(tree, regtab, reg)) != 0) 243: movreg(r, 0, tree); 244: return(0); 245: 246: /* 247: * sequential execution 248: */ 249: case SEQNC: 250: r = nstack; 251: rcexpr(tree->tr1, efftab, reg); 252: nstack = r; 253: atree = tree = tree->tr2; 254: goto again; 255: 256: /* 257: * In the generated &~ operator, 258: * fiddle things so a PDP-11 "bit" 259: * instruction will be produced when cctab is used. 260: */ 261: case ANDN: 262: if (table==cctab) { 263: tree->op = TAND; 264: tree->tr2 = optim(tnode(COMPL, tree->type, tree->tr2)); 265: } 266: break; 267: 268: /* 269: * Handle a subroutine call. It has to be done 270: * here because if cexpr got called twice, the 271: * arguments might be compiled twice. 272: * There is also some fiddling so the 273: * first argument, in favorable circumstances, 274: * goes to (sp) instead of -(sp), reducing 275: * the amount of stack-popping. 276: */ 277: case CALL: 278: r = 0; 279: nargs = 0; 280: modf = 0; 281: if (tree->tr1->op!=NAME || tree->tr1->class!=EXTERN) { 282: nargs++; 283: nstack++; 284: } 285: tree = tree->tr2; 286: if(tree->op) { 287: while (tree->op==COMMA) { 288: r =+ comarg(tree->tr2, &modf); 289: tree = tree->tr1; 290: nargs++; 291: } 292: r =+ comarg(tree, &modf); 293: nargs++; 294: } 295: tree = atree; 296: tree->op = CALL2; 297: if (modf && tree->tr1->op==NAME && tree->tr1->class==EXTERN) 298: tree->op = CALL1; 299: if (cexpr(tree, regtab, reg)<0) 300: error("compiler botch: call"); 301: popstk(r); 302: nstack =- nargs; 303: if (table==efftab || table==regtab) 304: return(0); 305: r = 0; 306: goto fixup; 307: 308: /* 309: * Longs need special treatment. 310: */ 311: case ASLSH: 312: case LSHIFT: 313: if (tree->type==LONG) { 314: if (tree->tr2->op==ITOL) 315: tree->tr2 = tree->tr2->tr1; 316: else 317: tree->tr2 = optim(tnode(LTOI,INT,tree->tr2)); 318: if (tree->op==ASLSH) 319: tree->op = ASLSHL; 320: else 321: tree->op = LLSHIFT; 322: } 323: break; 324: 325: /* 326: * Try to change * to shift. 327: */ 328: case TIMES: 329: case ASTIMES: 330: tree = pow2(tree); 331: } 332: /* 333: * Try to find postfix ++ and -- operators that can be 334: * pulled out and done after the rest of the expression 335: */ 336: if (table!=cctab && table!=cregtab && recurf<2 337: && (opdope[tree->op]&LEAF)==0) { 338: if (r=delay(&atree, table, reg)) { 339: tree = atree; 340: table = efftab; 341: reg = r-1; 342: } 343: } 344: /* 345: * Basically, try to reorder the computation 346: * so reg = x+y is done as reg = x; reg =+ y 347: */ 348: if (recurf==0 && reorder(&atree, table, reg)) { 349: if (table==cctab && atree->op==NAME) 350: return(reg); 351: } 352: tree = atree; 353: if (table==efftab && tree->op==NAME) 354: return(reg); 355: if ((r=cexpr(tree, table, reg))>=0) 356: return(r); 357: if (table!=regtab && (table!=cctab||(opdope[tree->op]&RELAT)==0)) { 358: if((r=cexpr(tree, regtab, reg))>=0) { 359: fixup: 360: modf = isfloat(tree); 361: dbprint(tree->op); 362: if (table==sptab || table==lsptab) { 363: if (tree->type==LONG) { 364: printf("mov\tr%d,-(sp)\n",r+1); 365: nstack++; 366: } 367: printf("mov%c r%d,%c(sp)\n", modf, r, 368: table==sptab? '-':0); 369: nstack++; 370: } 371: if (table==cctab) 372: printf("tst%c r%d\n", modf, r); 373: return(r); 374: } 375: } 376: /* 377: * There's a last chance for this operator 378: */ 379: if (tree->op==LTOI) { 380: r = rcexpr(tree->tr1, regtab, reg); 381: if (r >= 0) { 382: r++; 383: goto fixup; 384: } 385: } 386: if (tree->type == STRUCT) 387: error("Illegal operation on structure"); 388: else if (tree->op>0 && tree->op<RFORCE && opntab[tree->op]) 389: error("No code table for op: %s", opntab[tree->op]); 390: else 391: error("No code table for op %d", tree->op); 392: return(reg); 393: } 394: 395: /* 396: * Try to compile the tree with the code table using 397: * registers areg and up. If successful, 398: * return the register where the value actually ended up. 399: * If unsuccessful, return -1. 400: * 401: * Most of the work is the macro-expansion of the 402: * code table. 403: */ 404: cexpr(atree, table, areg) 405: struct tnode *atree; 406: struct table *table; 407: { 408: int c, r; 409: register struct tnode *p, *p1, *tree; 410: struct table *ctable; 411: struct tnode *p2; 412: char *string; 413: int reg, reg1, rreg, flag, opd; 414: char *opt; 415: 416: tree = atree; 417: reg = areg; 418: p1 = tree->tr2; 419: c = tree->op; 420: opd = opdope[c]; 421: /* 422: * When the value of a relational or a logical expression is 423: * desired, more work must be done. 424: */ 425: if ((opd&RELAT||c==LOGAND||c==LOGOR||c==EXCLA) && table!=cctab) { 426: cbranch(tree, c=isn++, 1, reg); 427: rcexpr(&czero, table, reg); 428: branch(isn, 0); 429: label(c); 430: rcexpr(&cone, table, reg); 431: label(isn++); 432: return(reg); 433: } 434: if(c==QUEST) { 435: if (table==cctab) 436: return(-1); 437: cbranch(tree->tr1, c=isn++, 0, reg); 438: flag = nstack; 439: rreg = rcexpr(p1->tr1, table, reg); 440: nstack = flag; 441: branch(r=isn++, 0); 442: label(c); 443: reg = rcexpr(p1->tr2, table, rreg); 444: if (rreg!=reg) 445: movreg(reg, rreg, tree->tr2); 446: label(r); 447: return(rreg); 448: } 449: reg = oddreg(tree, reg); 450: reg1 = reg+1; 451: /* 452: * long values take 2 registers. 453: */ 454: if ((tree->type==LONG||opd&RELAT&&tree->tr1->type==LONG) && tree->op!=ITOL) 455: reg1++; 456: /* 457: * Leaves of the expression tree 458: */ 459: if ((r = chkleaf(tree, table, reg)) >= 0) 460: return(r); 461: /* 462: * x + (-1) is better done as x-1. 463: */ 464: 465: if ((tree->op==PLUS||tree->op==ASPLUS) && 466: (p1=tree->tr2)->op == CON && p1->value == -1) { 467: p1->value = 1; 468: tree->op =+ (MINUS-PLUS); 469: } 470: /* 471: * Because of a peculiarity of the PDP11 table 472: * char = *intreg++ and *--intreg cannot go through. 473: */ 474: if (tree->tr1->type==CHAR && tree->tr2->type!=CHAR 475: && (tree->tr2->op==AUTOI||tree->tr2->op==AUTOD)) 476: tree->tr2 = tnode(LOAD, tree->tr2->type, tree->tr2); 477: if (table==cregtab) 478: table = regtab; 479: /* 480: * The following peculiar code depends on the fact that 481: * if you just want the codition codes set, efftab 482: * will generate the right code unless the operator is 483: * a shift or 484: * postfix ++ or --. Unravelled, if the table is 485: * cctab and the operator is not special, try first 486: * for efftab; if the table isn't, if the operator is, 487: * or the first match fails, try to match 488: * with the table actually asked for. 489: */ 490: /* 491: * Account for longs and oddregs; below is really 492: * r = nreg - reg - (reg-areg) - (reg1-reg-1); 493: */ 494: r = nreg - reg + areg - reg1 + 1; 495: if (table!=cctab || c==INCAFT || c==DECAFT || tree->type==LONG 496: || c==ASRSH || c==ASLSH || c==ASULSH 497: || (opt = match(tree, efftab, r, 0)) == 0) 498: if ((opt=match(tree, table, r, 0))==0) 499: return(-1); 500: string = opt->tabstring; 501: p1 = tree->tr1; 502: if (p1->op==FCON && p1->value>0) { 503: printf(".data\nL%d:%o;%o;%o;%o\n.text\n", p1->value, p1->fvalue); 504: p1->value = -p1->value; 505: } 506: p2 = 0; 507: if (opdope[tree->op]&BINARY) { 508: p2 = tree->tr2; 509: if (p2->op==FCON && p2->value>0) { 510: printf(".data\nL%d:%o;%o;%o;%o\n.text\n", p2->value, p2->fvalue); 511: p2->value = -p2->value; 512: } 513: } 514: loop: 515: /* 516: * The 0200 bit asks for a tab. 517: */ 518: if ((c = *string++) & 0200) { 519: c =& 0177; 520: putchar('\t'); 521: } 522: switch (c) { 523: 524: case '\n': 525: dbprint(tree->op); 526: break; 527: 528: case '\0': 529: if (!isfloat(tree)) 530: if (tree->op==DIVIDE||tree->op==ASDIV||tree->op==PTOI) 531: reg--; 532: return(reg); 533: 534: /* A1 */ 535: case 'A': 536: p = p1; 537: goto adr; 538: 539: /* A2 */ 540: case 'B': 541: p = p2; 542: goto adr; 543: 544: adr: 545: c = 0; 546: while (*string=='\'') { 547: c++; 548: string++; 549: } 550: if (*string=='+') { 551: c = 100; 552: string++; 553: } 554: pname(p, c); 555: goto loop; 556: 557: /* I */ 558: case 'M': 559: if ((c = *string)=='\'') 560: string++; 561: else 562: c = 0; 563: prins(tree->op, c, instab); 564: goto loop; 565: 566: /* B1 */ 567: case 'C': 568: if ((opd&LEAF) != 0) 569: p = tree; 570: else 571: p = p1; 572: goto pbyte; 573: 574: /* BF */ 575: case 'P': 576: p = tree; 577: goto pb1; 578: 579: /* B2 */ 580: case 'D': 581: p = p2; 582: pbyte: 583: if (p->type==CHAR) 584: putchar('b'); 585: pb1: 586: if (isfloat(p)) 587: putchar('f'); 588: goto loop; 589: 590: /* BE */ 591: case 'L': 592: if (p1->type==CHAR || p2->type==CHAR) 593: putchar('b'); 594: p = tree; 595: goto pb1; 596: 597: /* F */ 598: case 'G': 599: p = p1; 600: flag = 01; 601: goto subtre; 602: 603: /* S */ 604: case 'K': 605: p = p2; 606: flag = 02; 607: goto subtre; 608: 609: /* H */ 610: case 'H': 611: p = tree; 612: flag = 04; 613: 614: subtre: 615: ctable = regtab; 616: if (flag&04) 617: ctable = cregtab; 618: c = *string++ - 'A'; 619: if (*string=='!') { 620: string++; 621: c =| 020; /* force right register */ 622: } 623: if ((c&02)!=0) 624: ctable = sptab; 625: if ((c&04)!=0) 626: ctable = cctab; 627: if ((flag&01) && ctable==regtab && (c&01)==0 628: && (tree->op==DIVIDE||tree->op==MOD 629: || tree->op==ASDIV||tree->op==ASMOD||tree->op==ITOL)) 630: ctable = cregtab; 631: if ((c&01)!=0) { 632: p = p->tr1; 633: if(collcon(p) && ctable!=sptab) { 634: if (p->op==STAR) 635: p = p->tr1; 636: p = p->tr1; 637: } 638: } 639: if (table==lsptab && ctable==sptab) 640: ctable = lsptab; 641: if (c&010) 642: r = reg1; 643: else 644: if (opdope[p->op]&LEAF || p->degree < 2) 645: r = reg; 646: else 647: r = areg; 648: rreg = rcexpr(p, ctable, r); 649: if (ctable!=regtab && ctable!=cregtab) 650: goto loop; 651: if (c&010) { 652: if (c&020 && rreg!=reg1) 653: movreg(rreg, reg1, p); 654: else 655: reg1 = rreg; 656: } else if (rreg!=reg) 657: if ((c&020)==0 && oddreg(tree, 0)==0 && tree->type!=LONG 658: && (flag&04 659: || flag&01&&xdcalc(p2,nreg-rreg-1)<=(opt->tabdeg2&077) 660: || flag&02&&xdcalc(p1,nreg-rreg-1)<=(opt->tabdeg1&077))) { 661: reg = rreg; 662: reg1 = rreg+1; 663: } else 664: movreg(rreg, reg, p); 665: goto loop; 666: 667: /* R */ 668: case 'I': 669: r = reg; 670: if (*string=='-') { 671: string++; 672: r--; 673: } 674: goto preg; 675: 676: /* R1 */ 677: case 'J': 678: r = reg1; 679: preg: 680: if (*string=='+') { 681: string++; 682: r++; 683: } 684: if (r>nreg || r>=4 && tree->type==DOUBLE) 685: error("Register overflow: simplify expression"); 686: printf("r%d", r); 687: goto loop; 688: 689: case '-': /* check -(sp) */ 690: if (*string=='(') { 691: nstack++; 692: if (table!=lsptab) 693: putchar('-'); 694: goto loop; 695: } 696: break; 697: 698: case ')': /* check (sp)+ */ 699: putchar(')'); 700: if (*string=='+') 701: nstack--; 702: goto loop; 703: 704: /* #1 */ 705: case '#': 706: p = p1->tr1; 707: goto nmbr; 708: 709: /* #2 */ 710: case '"': 711: p = p2->tr1; 712: 713: nmbr: 714: if(collcon(p)) { 715: if (p->op==STAR) { 716: printf("*"); 717: p = p->tr1; 718: } 719: if ((p = p->tr2)->op == CON) { 720: if (p->value) 721: psoct(p->value); 722: } else if (p->op==AMPER) 723: pname(p->tr1, 0); 724: } 725: goto loop; 726: 727: /* 728: * Certain adjustments for / % and PTOI 729: */ 730: case 'T': 731: c = reg-1; 732: if (tree->op == PTOI) { 733: printf("bic r%d,r%d\nsbc r%d\n", c,c,c); 734: goto loop; 735: } 736: if (p1->type==UNSIGN || p1->type&XTYPE) { 737: printf("clr r%d\n", c); 738: goto loop; 739: } 740: if (dcalc(p1, 5)>12 && !match(p1, cctab, 10, 0)) 741: printf("tst r%d\n", reg); 742: printf("sxt r%d\n", c); 743: goto loop; 744: 745: case 'V': /* adc sbc, clr, or sxt as required for longs */ 746: switch(tree->op) { 747: case PLUS: 748: case ASPLUS: 749: case INCBEF: 750: case INCAFT: 751: printf("adc"); 752: break; 753: 754: case MINUS: 755: case ASMINUS: 756: case NEG: 757: case DECBEF: 758: case DECAFT: 759: printf("sbc"); 760: break; 761: 762: case ASSIGN: 763: p = tree->tr2; 764: goto lcasev; 765: 766: case ASDIV: 767: case ASMOD: 768: case ASULSH: 769: p = tree->tr1; 770: lcasev: 771: if (p->type!=LONG) { 772: if (p->type==UNSIGN || p->type&XTYPE) 773: printf("clr"); 774: else 775: printf("sxt"); 776: goto loop; 777: } 778: default: 779: while ((c = *string++)!='\n' && c!='\0'); 780: break; 781: } 782: goto loop; 783: 784: /* 785: * Mask used in field assignments 786: */ 787: case 'Z': 788: printf("$%o", tree->mask); 789: goto loop; 790: 791: /* 792: * Relational on long values. 793: * Might bug out early. E.g., 794: * (long<0) can be determined with only 1 test. 795: */ 796: case 'X': 797: if (xlongrel(*string++ - '0')) 798: return(reg); 799: goto loop; 800: } 801: putchar(c); 802: goto loop; 803: } 804: 805: /* 806: * This routine just calls sreorder (below) 807: * on the subtrees and then on the tree itself. 808: * It returns non-zero if anything changed. 809: */ 810: reorder(treep, table, reg) 811: struct tnode **treep; 812: struct table *table; 813: { 814: register r, o; 815: register struct tnode *p; 816: 817: p = *treep; 818: o = p->op; 819: if (opdope[o]&LEAF || o==LOGOR || o==LOGAND) 820: return(0); 821: while(sreorder(&p->tr1, regtab, reg, 1)) 822: ; 823: if (opdope[o]&BINARY) 824: while(sreorder(&p->tr2, regtab, reg, 1)) 825: ; 826: r = 0; 827: if (table!=cctab) 828: while (sreorder(treep, table, reg, 0)) 829: r++; 830: *treep = optim(*treep); 831: return(r); 832: } 833: 834: /* 835: * Basically this routine carries out two kinds of optimization. 836: * First, it observes that "x + (reg = y)" where actually 837: * the = is any assignment op is better done as "reg=y; x+reg". 838: * In this case rcexpr is called to do the first part and the 839: * tree is modified so the name of the register 840: * replaces the assignment. 841: * Moreover, expressions like "reg = x+y" are best done as 842: * "reg = x; reg =+ y" (so long as "reg" and "y" are not the same!). 843: */ 844: sreorder(treep, table, reg, recurf) 845: struct tnode **treep; 846: struct table *table; 847: { 848: register struct tnode *p, *p1; 849: 850: p = *treep; 851: if (opdope[p->op]&LEAF) 852: return(0); 853: if (p->op==PLUS && recurf) 854: if (reorder(&p->tr2, table, reg)) 855: *treep = p = optim(p); 856: p1 = p->tr1; 857: if (p->op==STAR || p->op==PLUS) { 858: if (recurf && reorder(&p->tr1, table, reg)) 859: *treep = p = optim(p); 860: p1 = p->tr1; 861: } 862: if (p1->op==NAME) switch(p->op) { 863: case ASLSH: 864: case ASRSH: 865: case ASSIGN: 866: if (p1->class != REG||p1->type==CHAR||isfloat(p->tr2)) 867: return(0); 868: if (p->op==ASSIGN) switch (p->tr2->op) { 869: case TIMES: 870: if (!ispow2(p->tr2)) 871: break; 872: p->tr2 = pow2(p->tr2); 873: case PLUS: 874: case MINUS: 875: case AND: 876: case ANDN: 877: case OR: 878: case EXOR: 879: case LSHIFT: 880: case RSHIFT: 881: p1 = p->tr2->tr2; 882: if (xdcalc(p1, 16) > 12 883: || p1->op==NAME 884: &&(p1->nloc==p->tr1->nloc 885: || p1->regno==p->tr1->nloc)) 886: return(0); 887: p1 = p->tr2; 888: p->tr2 = p1->tr1; 889: if (p1->tr1->op!=NAME 890: || p1->tr1->class!=REG 891: || p1->tr1->nloc!=p->tr1->nloc) 892: rcexpr(p, efftab, reg); 893: p->tr2 = p1->tr2; 894: p->op = p1->op + ASPLUS - PLUS; 895: *treep = p; 896: return(1); 897: } 898: goto OK; 899: 900: case ASTIMES: 901: if (!ispow2(p)) 902: return(0); 903: case ASPLUS: 904: case ASMINUS: 905: case ASAND: 906: case ASANDN: 907: case ASOR: 908: case ASXOR: 909: case INCBEF: 910: case DECBEF: 911: OK: 912: if (table==cctab||table==cregtab) 913: reg =+ 020; 914: rcexpr(optim(p), efftab, ~reg); 915: *treep = p1; 916: return(1); 917: } 918: return(0); 919: } 920: 921: /* 922: * Delay handles postfix ++ and -- 923: * It observes that "x + y++" is better 924: * treated as "x + y; y++". 925: * If the operator is ++ or -- itself, 926: * it calls rcexpr to load the operand, letting 927: * the calling instance of rcexpr to do the 928: * ++ using efftab. 929: * Otherwise it uses sdelay to search for inc/dec 930: * among the operands. 931: */ 932: delay(treep, table, reg) 933: struct tnode **treep; 934: { 935: register struct tnode *p, *p1; 936: register r; 937: 938: p = *treep; 939: if ((p->op==INCAFT||p->op==DECAFT) 940: && p->tr1->op==NAME) { 941: return(1+rcexpr(p->tr1, table, reg)); 942: } 943: p1 = 0; 944: if (opdope[p->op]&BINARY) { 945: if (p->op==LOGAND || p->op==LOGOR) 946: return(0); 947: } 948: p1 = sdelay(&p->tr2); 949: if (p1==0) 950: p1 = sdelay(&p->tr1); 951: if (p1) { 952: r = rcexpr(optim(p), table, reg); 953: *treep = p1; 954: return(r+1); 955: } 956: return(0); 957: } 958: 959: sdelay(ap) 960: struct tnode **ap; 961: { 962: register struct tnode *p, *p1; 963: 964: p = *ap; 965: if ((p->op==INCAFT||p->op==DECAFT) && p->tr1->op==NAME) { 966: *ap = ncopy(p->tr1); 967: return(p); 968: } 969: if (p->op==STAR || p->op==PLUS) 970: if (p1=sdelay(&p->tr1)) 971: return(p1); 972: if (p->op==PLUS) 973: return(sdelay(&p->tr2)); 974: return(0); 975: } 976: 977: /* 978: * Copy a tree node for a register variable. 979: * Used by sdelay because if *reg-- is turned 980: * into *reg; reg-- the *reg will in turn 981: * be changed to some offset class, accidentally 982: * modifying the reg--. 983: */ 984: ncopy(ap) 985: struct tname *ap; 986: { 987: register struct tname *p, *q; 988: 989: p = ap; 990: if (p->class!=REG) 991: return(p); 992: q = getblk(sizeof(*p)); 993: q->op = p->op; 994: q->type = p->type; 995: q->class = p->class; 996: q->offset = p->offset; 997: q->nloc = p->nloc; 998: return(q); 999: } 1000: 1001: /* 1002: * If the tree can be immediately loaded into a register, 1003: * produce code to do so and return success. 1004: */ 1005: chkleaf(atree, table, reg) 1006: struct tnode *atree; 1007: { 1008: struct tnode lbuf; 1009: register struct tnode *tree; 1010: 1011: tree = atree; 1012: if (tree->op!=STAR && dcalc(tree, nreg-reg) > 12) 1013: return(-1); 1014: lbuf.op = LOAD; 1015: lbuf.type = tree->type; 1016: lbuf.degree = tree->degree; 1017: lbuf.tr1 = tree; 1018: return(rcexpr(&lbuf, table, reg)); 1019: } 1020: 1021: /* 1022: * Compile a function argument. 1023: * If the stack is currently empty, put it in (sp) 1024: * rather than -(sp); this will save a pop. 1025: * Return the number of bytes pushed, 1026: * for future popping. 1027: */ 1028: comarg(atree, flagp) 1029: int *flagp; 1030: { 1031: register struct tnode *tree; 1032: register retval; 1033: int i; 1034: int size; 1035: 1036: tree = atree; 1037: if (tree->op==STRASG) { 1038: size = tree->mask; 1039: tree = tree->tr1; 1040: tree = strfunc(tree); 1041: if (size <= 2) { 1042: setype(tree, INT); 1043: goto normal; 1044: } 1045: if (size <= 4) { 1046: setype(tree, LONG); 1047: goto normal; 1048: } 1049: if (tree->op!=NAME && tree->op!=STAR) { 1050: error("Unimplemented structure assignment"); 1051: return(0); 1052: } 1053: tree = tnode(AMPER, STRUCT+PTR, tree); 1054: tree = tnode(PLUS, STRUCT+PTR, tree, tconst(size, INT)); 1055: tree = optim(tree); 1056: retval = rcexpr(tree, regtab, 0); 1057: size =>> 1; 1058: if (size <= 5) { 1059: for (i=0; i<size; i++) 1060: printf("mov -(r%d),-(sp)\n", retval); 1061: } else { 1062: if (retval!=0) 1063: printf("mov r%d,r0\n", retval); 1064: printf("mov $%o,r1\n", size); 1065: printf("L%d:mov -(r0),-(sp)\ndec\tr1\njne\tL%d\n", isn, isn); 1066: isn++; 1067: } 1068: nstack++; 1069: return(size*2); 1070: } 1071: normal: 1072: if (nstack || isfloat(tree) || tree->type==LONG) { 1073: rcexpr(tree, sptab, 0); 1074: retval = arlength(tree->type); 1075: } else { 1076: (*flagp)++; 1077: rcexpr(tree, lsptab, 0); 1078: retval = 0; 1079: } 1080: return(retval); 1081: } 1082: 1083: struct tnode * 1084: strfunc(atp) 1085: struct tnode *atp; 1086: { 1087: register struct tnode *tp; 1088: 1089: tp = atp; 1090: if (tp->op != CALL) 1091: return(tp); 1092: setype(tp, STRUCT+PTR); 1093: return(tnode(STAR, STRUCT, tp)); 1094: } 1095: 1096: /* 1097: * Compile an initializing expression 1098: */ 1099: doinit(atype, atree) 1100: struct tnode *atree; 1101: { 1102: register struct tnode *tree; 1103: register int type; 1104: float sfval; 1105: double fval; 1106: long lval; 1107: 1108: tree = atree; 1109: type = atype; 1110: if (type==CHAR) { 1111: printf(".byte "); 1112: if (tree->type&XTYPE) 1113: goto illinit; 1114: type = INT; 1115: } 1116: if (type&XTYPE) 1117: type = INT; 1118: switch (type) { 1119: case INT: 1120: case UNSIGN: 1121: if (tree->op==FTOI) { 1122: if (tree->tr1->op!=FCON && tree->tr1->op!=SFCON) 1123: goto illinit; 1124: tree = tree->tr1; 1125: tree->value = tree->fvalue; 1126: tree->op = CON; 1127: } else if (tree->op==LTOI) { 1128: if (tree->tr1->op!=LCON) 1129: goto illinit; 1130: tree = tree->tr1; 1131: lval = tree->lvalue; 1132: tree->op = CON; 1133: tree->value = lval; 1134: } 1135: if (tree->op == CON) 1136: printf("%o\n", tree->value); 1137: else if (tree->op==AMPER) { 1138: pname(tree->tr1, 0); 1139: putchar('\n'); 1140: } else 1141: goto illinit; 1142: return; 1143: 1144: case DOUBLE: 1145: case FLOAT: 1146: if (tree->op==ITOF) { 1147: if (tree->tr1->op==CON) { 1148: fval = tree->tr1->value; 1149: } else 1150: goto illinit; 1151: } else if (tree->op==FCON || tree->op==SFCON) 1152: fval = tree->fvalue; 1153: else if (tree->op==LTOF) { 1154: if (tree->tr1->op!=LCON) 1155: goto illinit; 1156: fval = tree->tr1->lvalue; 1157: } else 1158: goto illinit; 1159: if (type==FLOAT) { 1160: sfval = fval; 1161: printf("%o; %o\n", sfval); 1162: } else 1163: printf("%o; %o; %o; %o\n", fval); 1164: return; 1165: 1166: case LONG: 1167: if (tree->op==FTOL) { 1168: tree = tree->tr1; 1169: if (tree->op==SFCON) 1170: tree->op = FCON; 1171: if (tree->op!= FCON) 1172: goto illinit; 1173: lval = tree->fvalue; 1174: } else if (tree->op==ITOL) { 1175: if (tree->tr1->op != CON) 1176: goto illinit; 1177: lval = tree->tr1->value; 1178: } else if (tree->op==LCON) 1179: lval = tree->lvalue; 1180: else 1181: goto illinit; 1182: printf("%o; %o\n", lval); 1183: return; 1184: } 1185: illinit: 1186: error("Illegal initialization"); 1187: } 1188: 1189: movreg(r0, r1, tree) 1190: struct tnode *tree; 1191: { 1192: register char *s; 1193: 1194: if (r0==r1) 1195: return; 1196: if (tree->type==LONG) { 1197: s = "mov r%d,r%d\nmov r%d,r%d\n"; 1198: if (r0 < r1) 1199: printf(s, r0+1,r1+1,r0,r1); 1200: else 1201: printf(s, r0,r1,r0+1,r1+1); 1202: return; 1203: } 1204: printf("mov%c r%d,r%d\n", isfloat(tree), r0, r1); 1205: }