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: }

Defined functions

cexpr defined in line 404; used 4 times
chkleaf defined in line 1005; used 1 times
comarg defined in line 1028; used 2 times
delay defined in line 932; used 1 times
doinit defined in line 1099; used 1 times
main defined in line 35; never used
match defined in line 90; used 5 times
movreg defined in line 1189; used 4 times
ncopy defined in line 984; used 1 times
rcexpr defined in line 181; used 16 times
reorder defined in line 810; used 4 times
sdelay defined in line 959; used 4 times
sreorder defined in line 844; used 3 times
strfunc defined in line 1083; used 2 times

Defined variables

cone defined in line 26; used 1 times
cregtab defined in line 30; used 6 times
czero defined in line 25; used 1 times
isn defined in line 33; used 8 times
maprel defined in line 17; never used
notrel defined in line 21; never used
nreg defined in line 32; used 5 times
sccsid defined in line 1; never used
sfuncr defined in line 28; never used

Defined macros

NOCVL defined in line 95; used 2 times
NOCVR defined in line 96; used 2 times
dbprint defined in line 14; used 2 times
Last modified: 1981-07-10
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 2189
Valid CSS Valid XHTML 1.0 Strict