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