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

Defined functions

cexpr defined in line 399; used 4 times
chkleaf defined in line 1000; used 1 times
comarg defined in line 1023; used 2 times
delay defined in line 927; used 1 times
doinit defined in line 1094; used 1 times
main defined in line 34; never used
match defined in line 85; used 5 times
movreg defined in line 1184; used 4 times
ncopy defined in line 979; used 1 times
rcexpr defined in line 176; used 16 times
reorder defined in line 805; used 4 times
sdelay defined in line 954; used 4 times
sreorder defined in line 839; used 3 times
strfunc defined in line 1078; used 2 times

Defined variables

cone defined in line 25; used 1 times
cregtab defined in line 29; used 6 times
czero defined in line 24; used 1 times
isn defined in line 32; used 8 times
maprel defined in line 16; never used
notrel defined in line 20; never used
nreg defined in line 31; used 5 times
sfuncr defined in line 27; never used

Defined macros

NOCVL defined in line 90; used 2 times
NOCVR defined in line 91; used 2 times
dbprint defined in line 13; used 2 times
Last modified: 1979-05-07
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 2191
Valid CSS Valid XHTML 1.0 Strict