1: /*
   2:  *  C compiler
   3:  */
   4: 
   5: #include "c1.h"
   6: 
   7: degree(t)
   8: register union tree *t;
   9: {
  10:     register union tree *t1;
  11: 
  12:     if (t==NULL || t->t.op==0)
  13:         return(0);
  14:     if (t->t.op == CON)
  15:         return(-3);
  16:     if (t->t.op == AMPER)
  17:         return(-2);
  18:     if (t->t.op==ITOL) {
  19:         if ((t1 = isconstant(t)) && (t1->c.value>=0 || uns(t1)))
  20:             return(-2);
  21:         if (uns(t1 = t->t.tr1) && opdope[t1->t.op]&LEAF)
  22:             return(-1);
  23:     }
  24:     if ((opdope[t->t.op] & LEAF) != 0) {
  25:         if (t->t.type==CHAR || t->t.type==UNCHAR || t->t.type==FLOAT)
  26:             return(1);
  27:         return(0);
  28:     }
  29:     return(t->t.degree);
  30: }
  31: 
  32: pname(p, flag)
  33: register union tree *p;
  34: {
  35:     register i;
  36: 
  37: loop:
  38:     switch(p->t.op) {
  39: 
  40:     case LCON:
  41:         printf("$%o", flag<=10? UNS(p->l.lvalue>>16):
  42:            UNS(p->l.lvalue));
  43:         return;
  44: 
  45:     case SFCON:
  46:     case CON:
  47:         printf("$");
  48:         psoct(p->c.value);
  49:         return;
  50: 
  51:     case FCON:
  52:         printf("L%d", (p->c.value>0? p->c.value: -p->c.value));
  53:         return;
  54: 
  55:     case NAME:
  56:         i = p->n.offset;
  57:         if (flag>10)
  58:             i += 2;
  59:         if (i) {
  60:             psoct(i);
  61:             if (p->n.class!=OFFS)
  62:                 putchar('+');
  63:             if (p->n.class==REG)
  64:                 error("Illegal use of register");
  65:         }
  66:         switch(p->n.class) {
  67: 
  68:         case SOFFS:
  69:         case XOFFS:
  70:             pbase(p);
  71: 
  72:         case OFFS:
  73:             printf("(r%d)", p->n.regno);
  74:             return;
  75: 
  76:         case EXTERN:
  77:         case STATIC:
  78:             pbase(p);
  79:             return;
  80: 
  81:         case REG:
  82:             printf("r%d", p->n.nloc);
  83:             return;
  84: 
  85:         }
  86:         error("Compiler error: pname");
  87:         return;
  88: 
  89:     case AMPER:
  90:         putchar('$');
  91:         p = p->t.tr1;
  92:         if (p->t.op==NAME && p->n.class==REG)
  93:             error("Illegal use of register");
  94:         goto loop;
  95: 
  96:     case AUTOI:
  97:         printf("(r%d)%s", p->n.nloc, flag==1?"":"+");
  98:         return;
  99: 
 100:     case AUTOD:
 101:         printf("%s(r%d)", flag==2?"":"-", p->n.nloc);
 102:         return;
 103: 
 104:     case STAR:
 105:         p = p->t.tr1;
 106:         putchar('*');
 107:         goto loop;
 108: 
 109:     }
 110:     error("compiler error: bad pname");
 111: }
 112: 
 113: pbase(p)
 114: register union tree *p;
 115: {
 116: 
 117:     if (p->n.class==SOFFS || p->n.class==STATIC)
 118:         printf("L%d", p->n.nloc);
 119:     else
 120:         printf("%s", p->x.name);
 121: }
 122: 
 123: xdcalc(p, nrleft)
 124: register union tree *p;
 125: {
 126:     register d;
 127: 
 128:     if (p==NULL)
 129:         return(0);
 130:     d = dcalc(p, nrleft);
 131:     if (d<20 && (p->t.type==CHAR || p->t.type==UNCHAR)) {
 132:         if (nrleft>=1)
 133:             d = 20;
 134:         else
 135:             d = 24;
 136:     }
 137:     return(d);
 138: }
 139: 
 140: dcalc(p, nrleft)
 141: register union tree *p;
 142: {
 143:     register union tree *p1;
 144: 
 145:     if (p==NULL)
 146:         return(0);
 147:     switch (p->t.op) {
 148: 
 149:     case NAME:
 150:         if (p->n.class==REG && p->n.type!=CHAR && p->n.type!=UNCHAR)
 151:             return(9);
 152: 
 153:     case AMPER:
 154:     case FCON:
 155:     case LCON:
 156:     case AUTOI:
 157:     case AUTOD:
 158:         return(12);
 159: 
 160:     case CON:
 161:     case SFCON:
 162:         if (p->c.value==0)
 163:             return(4);
 164:         if (p->c.value==1)
 165:             return(5);
 166:         if (p->c.value > 0)
 167:             return(8);
 168:         return(12);
 169: 
 170:     case STAR:
 171:         p1 = p->t.tr1;
 172:         if (p1->t.op==NAME||p1->t.op==CON||p1->t.op==AUTOI||p1->t.op==AUTOD)
 173:             if (p->t.type!=LONG && p->t.type!=UNLONG)
 174:                 return(12);
 175:     }
 176:     if (p->t.type==LONG || p->t.type==UNLONG)
 177:         nrleft--;
 178:     return(p->t.degree <= nrleft? 20: 24);
 179: }
 180: 
 181: notcompat(p, ast, deg, op)
 182: register union tree *p;
 183: {
 184:     unsigned register at, st;
 185: 
 186:     at = p->t.type;
 187:     /*
 188: 	 * an e or n UNCHAR is to be considered an UNSIGNED,
 189: 	 * as long as it is not pointed to.
 190: 	 */
 191:     if (at==UNCHAR && deg<0100 && deg>=20)
 192:         at = UNSIGN;
 193:     st = ast;
 194:     if (st==0)      /* word, byte */
 195:         return(at!=CHAR && at!=INT && at!=UNSIGN && at<PTR);
 196:     if (st==1)      /* word */
 197:         return(at!=INT && at!=UNSIGN && at<PTR);
 198:     if (st==9 && (at&XTYPE))
 199:         return(0);
 200:     st -= 2;
 201:     if ((at&(~(TYPE+XTYPE))) != 0)
 202:         at = 020;
 203:     if ((at&(~TYPE)) != 0)
 204:         at = at&TYPE | 020;
 205:     if (st==FLOAT && at==DOUBLE)
 206:         at = FLOAT;
 207:     if (p->t.op==NAME && p->n.class==REG && op==ASSIGN && st==CHAR)
 208:         return(0);
 209:     return(st != at);
 210: }
 211: 
 212: prins(op, c, itable, lbl)
 213: struct instab *itable;
 214: {
 215:     extern char jmijne[];
 216:     register struct instab  *insp;
 217:     register char   *ip;
 218:     register int    skip;
 219: 
 220:     skip = 0;
 221:     for (insp = itable; insp->iop != 0; insp++) {
 222:         if (insp->iop == op) {
 223:             ip = c ? insp->str2: insp->str1;
 224:             if (!ip)
 225:                 break;
 226:             if (ip != jmijne) {
 227:                 printf(ip, lbl);
 228:             }
 229:             else {
 230:                 skip = isn++;
 231:                 printf(ip, skip);
 232:             }
 233:             return(skip);
 234:         }
 235:     }
 236:     error("No match' for op %d", op);
 237:     return(skip);
 238: }
 239: 
 240: collcon(p)
 241: register union tree *p;
 242: {
 243:     register op;
 244: 
 245:     if (p==NULL)
 246:         return(0);
 247:     if (p->t.op==STAR) {
 248:         if (p->t.type==LONG+PTR || p->t.type==UNLONG+PTR) /* avoid *x(r); *x+2(r) */
 249:             return(0);
 250:         p = p->t.tr1;
 251:     }
 252:     if (p->t.op==PLUS) {
 253:         op = p->t.tr2->t.op;
 254:         if (op==CON || op==AMPER)
 255:             return(1);
 256:     }
 257:     return(0);
 258: }
 259: 
 260: isfloat(t)
 261: register union tree *t;
 262: {
 263: 
 264:     if ((opdope[t->t.op]&RELAT)!=0)
 265:         t = t->t.tr1;
 266:     if (t->t.type==FLOAT || t->t.type==DOUBLE) {
 267:         nfloat = 1;
 268:         return('f');
 269:     }
 270:     return(0);
 271: }
 272: 
 273: oddreg(t, reg)
 274: register union tree *t;
 275: register reg;
 276: {
 277: 
 278:     if (!isfloat(t)) {
 279:         if (opdope[t->t.op]&RELAT) {
 280:             if (t->t.tr1->t.type==LONG || t->t.tr1->t.type==UNLONG)
 281:                 return((reg+1) & ~01);
 282:             return(reg);
 283:         }
 284:         switch(t->t.op) {
 285:         case ULLSHIFT:
 286:         case UASLSHL:
 287:         case LLSHIFT:
 288:         case ASLSHL:
 289:         case PTOI:
 290:             return((reg+1)&~01);
 291: 
 292:         case DIVIDE:
 293:         case MOD:
 294:         case ASDIV:
 295:         case ASMOD:
 296:         case ULSH:
 297:         case ASULSH:
 298:             reg++;
 299: 
 300:         case TIMES:
 301:         case ASTIMES:
 302:             return(reg|1);
 303:         }
 304:     }
 305:     return(reg);
 306: }
 307: 
 308: arlength(t)
 309: {
 310:     if (t>=PTR)
 311:         return(2);
 312:     switch(t) {
 313: 
 314:     case INT:
 315:     case CHAR:
 316:     case UNSIGN:
 317:     case UNCHAR:
 318:         return(2);
 319: 
 320:     case UNLONG:
 321:     case LONG:
 322:         return(4);
 323: 
 324:     case FLOAT:
 325:     case DOUBLE:
 326:         return(8);
 327:     }
 328:     error("botch: peculiar type %d", t);
 329:     return(1024);
 330: }
 331: 
 332: /*
 333:  * Strings for switch code.
 334:  */
 335: 
 336: /*
 337:  * Modified Memorial day May 80 to uniquely identify switch tables
 338:  * (as on Vax) so a shell script can optionally include them in RO code.
 339:  * This is useful in overlays to reduce the size of data space load.
 340:  * wfj 5/80
 341:  */
 342: char    dirsw[] = {"\
 343: cmp	r0,$%o\n\
 344: jhi	L%d\n\
 345: asl	r0\n\
 346: jmp	*L%d(r0)\n\
 347: \t.data\n\
 348: L%d:\
 349: " };
 350: 
 351: char    hashsw[] = {"\
 352: mov	r0,r1\n\
 353: clr	r0\n\
 354: div	$%o,r0\n\
 355: asl	r1\n\
 356: jmp	*L%d(r1)\n\
 357: \t.data\n\
 358: L%d:\
 359: "};
 360: 
 361: /*
 362:  * If the unsigned casts below won't compile,
 363:  * try using the calls to lrem and ldiv.
 364:  */
 365: 
 366: pswitch(afp, alp, deflab)
 367: struct swtab *afp, *alp;
 368: {
 369:     int ncase, i, j, tabs, worst, best, range;
 370:     register struct swtab *swp, *fp, *lp;
 371:     int *poctab;
 372: 
 373:     fp = afp;
 374:     lp = alp;
 375:     if (fp==lp) {
 376:         printf("jbr	L%d\n", deflab);
 377:         return;
 378:     }
 379:     isn++;
 380:     if (sort(fp, lp))
 381:         return;
 382:     ncase = lp-fp;
 383:     lp--;
 384:     range = lp->swval - fp->swval;
 385:     /* direct switch */
 386:     if (range>0 && range <= 3*ncase) {
 387:         if (fp->swval)
 388:             printf("sub	$%o,r0\n", UNS(fp->swval));
 389:         printf(dirsw, UNS(range), deflab, isn, isn);
 390:         isn++;
 391:         for (i=fp->swval; ; i++) {
 392:             if (i==fp->swval) {
 393:                 printf("L%d\n", fp->swlab);
 394:                 if (fp==lp)
 395:                     break;
 396:                 fp++;
 397:             } else
 398:                 printf("L%d\n", deflab);
 399:         }
 400:         printf(".text\n");
 401:         return;
 402:     }
 403:     /* simple switch */
 404:     if (ncase<10) {
 405:         for (fp = afp; fp<=lp; fp++)
 406:             breq(fp->swval, fp->swlab);
 407:         printf("jbr	L%d\n", deflab);
 408:         return;
 409:     }
 410:     /* hash switch */
 411:     best = 077777;
 412:     poctab = (int *)getblk(((ncase+2)/2) * sizeof(*poctab));
 413:     for (i=ncase/4; i<=ncase/2; i++) {
 414:         for (j=0; j<i; j++)
 415:             poctab[j] = 0;
 416:         for (swp=fp; swp<=lp; swp++)
 417:             /* lrem(0, swp->swval, i) */
 418:             poctab[(unsigned)swp->swval%i]++;
 419:         worst = 0;
 420:         for (j=0; j<i; j++)
 421:             if (poctab[j]>worst)
 422:                 worst = poctab[j];
 423:         if (i*worst < best) {
 424:             tabs = i;
 425:             best = i*worst;
 426:         }
 427:     }
 428:     i = isn++;
 429:     printf(hashsw, UNS(tabs), i, i);
 430:     isn++;
 431:     for (i=0; i<tabs; i++)
 432:         printf("L%d\n", isn+i);
 433:     printf(".text\n");
 434:     for (i=0; i<tabs; i++) {
 435:         printf("L%d:", isn++);
 436:         for (swp=fp; swp<=lp; swp++) {
 437:             /* lrem(0, swp->swval, tabs) */
 438:             if ((unsigned)swp->swval%tabs == i) {
 439:                 /* ldiv(0, swp->swval, tabs) */
 440:                 breq((int)((unsigned)swp->swval/tabs), swp->swlab);
 441:             }
 442:         }
 443:         printf("jbr	L%d\n", deflab);
 444:     }
 445: }
 446: 
 447: breq(v, l)
 448: {
 449:     if (v==0)
 450:         printf("tst	r0\n");
 451:     else
 452:         printf("cmp	r0,$%o\n", UNS(v));
 453:     printf("jeq	L%d\n", l);
 454: }
 455: 
 456: sort(afp, alp)
 457: struct swtab *afp, *alp;
 458: {
 459:     register struct swtab *cp, *fp, *lp;
 460:     int intch, t;
 461: 
 462:     fp = afp;
 463:     lp = alp;
 464:     while (fp < --lp) {
 465:         intch = 0;
 466:         for (cp=fp; cp<lp; cp++) {
 467:             if (cp->swval == cp[1].swval) {
 468:                 error("Duplicate case (%d)", cp->swval);
 469:                 return(1);
 470:             }
 471:             if (cp->swval > cp[1].swval) {
 472:                 intch++;
 473:                 t = cp->swval;
 474:                 cp->swval = cp[1].swval;
 475:                 cp[1].swval = t;
 476:                 t = cp->swlab;
 477:                 cp->swlab = cp[1].swlab;
 478:                 cp[1].swlab = t;
 479:             }
 480:         }
 481:         if (intch==0)
 482:             break;
 483:     }
 484:     return(0);
 485: }
 486: 
 487: ispow2(tree)
 488: register union tree *tree;
 489: {
 490:     register int d;
 491: 
 492:     if (!isfloat(tree) && tree->t.tr2->t.op==CON) {
 493:         d = tree->t.tr2->c.value;
 494:         if (d>1 && (d&(d-1))==0)
 495:             return(d);
 496:     }
 497:     return(0);
 498: }
 499: 
 500: union tree *
 501: pow2(tree)
 502: register union tree *tree;
 503: {
 504:     register int d, i;
 505: 
 506:     if (d = ispow2(tree)) {
 507:         for (i=0; (d>>=1)!=0; i++);
 508:         tree->t.tr2->c.value = i;
 509:         switch (tree->t.op) {
 510: 
 511:         case TIMES:
 512:             tree->t.op = LSHIFT;
 513:             break;
 514: 
 515:         case ASTIMES:
 516:             tree->t.op = ASLSH;
 517:             break;
 518: 
 519:         case PTOI:
 520:             if (i==1 && tree->t.tr1->t.op==MINUS && !isconstant(tree->t.tr1->t.tr2)) {
 521:                 tree->t.op = PTOI1;
 522:                 tree->t.tr1 = tnode(LTOI, INT, tree->t.tr1, TNULL);
 523:                 return(optim(tree));
 524:             }
 525:             tree->t.op = LLSHIFT;
 526:             tree->t.tr2->c.value = -i;
 527:             i = tree->t.type;
 528:             tree->t.type = LONG;
 529:             tree = tnode(LTOI, i, tree, TNULL);
 530:             break;
 531: 
 532:         case DIVIDE:
 533:             tree->t.op = ULSH;
 534:             tree->t.tr2->c.value = -i;
 535:             break;
 536: 
 537:         case ASDIV:
 538:             tree->t.op = ASULSH;
 539:             tree->t.tr2->c.value = -i;
 540:             break;
 541: 
 542:         case MOD:
 543:             tree->t.op = AND;
 544:             tree->t.tr2->c.value = (1<<i)-1;
 545:             break;
 546: 
 547:         case ASMOD:
 548:             tree->t.op = ASAND;
 549:             tree->t.tr2->c.value = (1<<i)-1;
 550:             break;
 551: 
 552:         default:
 553:             error("pow2 botch");
 554:         }
 555:         tree = optim(tree);
 556:     }
 557:     return(tree);
 558: }
 559: 
 560: cbranch(atree, lbl, cond, reg)
 561: union tree *atree;
 562: register lbl, reg;
 563: {
 564:     int l1, op;
 565:     register union tree *tree;
 566: 
 567: again:
 568:     if ((tree=atree)==NULL)
 569:         return;
 570:     switch(tree->t.op) {
 571: 
 572:     case LOGAND:
 573:         if (cond) {
 574:             cbranch(tree->t.tr1, l1=isn++, 0, reg);
 575:             cbranch(tree->t.tr2, lbl, 1, reg);
 576:             label(l1);
 577:         } else {
 578:             cbranch(tree->t.tr1, lbl, 0, reg);
 579:             cbranch(tree->t.tr2, lbl, 0, reg);
 580:         }
 581:         return;
 582: 
 583:     case LOGOR:
 584:         if (cond) {
 585:             cbranch(tree->t.tr1, lbl, 1, reg);
 586:             cbranch(tree->t.tr2, lbl, 1, reg);
 587:         } else {
 588:             cbranch(tree->t.tr1, l1=isn++, 1, reg);
 589:             cbranch(tree->t.tr2, lbl, 0, reg);
 590:             label(l1);
 591:         }
 592:         return;
 593: 
 594:     case EXCLA:
 595:         cbranch(tree->t.tr1, lbl, !cond, reg);
 596:         return;
 597: 
 598:     case SEQNC:
 599:         rcexpr(tree->t.tr1, efftab, reg);
 600:         atree = tree->t.tr2;
 601:         goto again;
 602: 
 603:     case ITOL:
 604:         tree = tree->t.tr1;
 605:         break;
 606: 
 607:     case QUEST:
 608:         l1 = isn;
 609:         isn += 2;
 610:         cbranch(tree->t.tr1, l1, 0, reg);
 611:         cbranch(tree->t.tr2->t.tr1, lbl, cond, reg);
 612:         branch(l1+1, 0, 0);
 613:         label(l1);
 614:         cbranch(tree->t.tr2->t.tr2, lbl, cond, reg);
 615:         label(l1+1);
 616:         return;
 617: 
 618:     }
 619:     op = tree->t.op;
 620:     if (opdope[op]&RELAT
 621:      && tree->t.tr1->t.op==ITOL && tree->t.tr2->t.op==ITOL
 622:      && uns(tree->t.tr1->t.tr1) == uns(tree->t.tr2->t.tr1)) {
 623:         tree->t.tr1 = tree->t.tr1->t.tr1;
 624:         tree->t.tr2 = tree->t.tr2->t.tr1;
 625:         if (op>=LESSEQ && op<=GREAT
 626:          && uns(tree->t.tr1))
 627:             tree->t.op = op = op+LESSEQP-LESSEQ;
 628:     }
 629:     if (tree->t.type==LONG || tree->t.type==UNLONG
 630:       || opdope[op]&RELAT&&(tree->t.tr1->t.type==LONG || tree->t.tr1->t.type==UNLONG)) {
 631:         longrel(tree, lbl, cond, reg);
 632:         return;
 633:     }
 634:     rcexpr(tree, cctab, reg);
 635:     op = tree->t.op;
 636:     if ((opdope[op]&RELAT)==0)
 637:         op = NEQUAL;
 638:     else {
 639:         l1 = tree->t.tr2->t.op;
 640:         if ((l1==CON || l1==SFCON) && tree->t.tr2->c.value==0)
 641:             op += 200;      /* special for ptr tests */
 642:         else
 643:             op = maprel[op-EQUAL];
 644:     }
 645:     if (isfloat(tree))
 646:         printf("cfcc\n");
 647:     branch(lbl, op, !cond);
 648: }
 649: 
 650: branch(lbl, aop, c)
 651: {
 652:     register int    op,
 653:             skip;
 654: 
 655:     if(op = aop) {
 656:         skip = prins(op, c, branchtab, lbl);
 657:     } else {
 658:         printf("jbr");
 659:         skip = 0;
 660:     }
 661:     if (skip)
 662:         printf("\tL%d\nL%d:", lbl, skip);
 663:     else
 664:         printf("\tL%d\n", lbl);
 665: }
 666: 
 667: longrel(atree, lbl, cond, reg)
 668: union tree *atree;
 669: {
 670:     int xl1, xl2, xo, xz;
 671:     register int op, isrel;
 672:     register union tree *tree;
 673: 
 674:     if (reg&01)
 675:         reg++;
 676:     reorder(&atree, cctab, reg);
 677:     tree = atree;
 678:     isrel = 0;
 679:     if (opdope[tree->t.op]&RELAT) {
 680:         isrel++;
 681:         op = tree->t.op;
 682:     } else
 683:         op = NEQUAL;
 684:     if (!cond)
 685:         op = notrel[op-EQUAL];
 686:     xl1 = xlab1;
 687:     xl2 = xlab2;
 688:     xo = xop;
 689:     xlab1 = lbl;
 690:     xlab2 = 0;
 691:     xop = op;
 692:     xz = xzero;
 693:     xzero = !isrel || (tree->t.tr2->t.op==ITOL && tree->t.tr2->t.tr1->t.op==CON
 694:         && tree->t.tr2->t.tr1->c.value==0);
 695:     if (tree->t.op==ANDN) {
 696:         tree->t.op = TAND;
 697:         tree->t.tr2 = optim(tnode(COMPL, LONG, tree->t.tr2, TNULL));
 698:     }
 699:     if (cexpr(tree, cctab, reg) < 0) {
 700:         reg = rcexpr(tree, regtab, reg);
 701:         printf("ashc	$0,r%d\n", reg);
 702:         branch(xlab1, op, 0);
 703:     }
 704:     xlab1 = xl1;
 705:     xlab2 = xl2;
 706:     xop = xo;
 707:     xzero = xz;
 708: }
 709: 
 710: /*
 711:  * Tables for finding out how best to do long comparisons.
 712:  * First dimen is whether or not the comparison is with 0.
 713:  * Second is which test: e.g. a>b->
 714:  *	cmp	a,b
 715:  *	bgt	YES		(first)
 716:  *	blt	NO		(second)
 717:  *	cmp	a+2,b+2
 718:  *	bhi	YES		(third)
 719:  *  NO:	...
 720:  * Note some tests may not be needed.
 721:  *
 722:  * EQUAL = 60
 723:  * NEQUAL= 61
 724:  * LESSEQ= 62
 725:  * LESS  = 63
 726:  * GREATEQ=64
 727:  * GREAT  =65
 728:  * LESSEQP=66
 729:  * LESSP  =67
 730:  * GREATQP=68
 731:  * GREATP =69
 732:  *
 733:  * Third dimension (lrtab[][][x]) indexed by "x - EQUAL".
 734:  */
 735: char    lrtab[2][3][10] = {
 736:     0, NEQUAL, LESS, LESS, GREAT, GREAT, LESSP, LESSP, GREATP, GREATP,
 737:     NEQUAL, 0, GREAT, GREAT, LESS, LESS, GREATP, GREATP, LESSP, LESSP,
 738:     EQUAL,NEQUAL,LESSEQP,LESSP, GREATQP,GREATP,LESSEQP,LESSP,GREATQP,GREATP,
 739: 
 740:     0, NEQUAL, LESS, LESS,  GREATEQ,GREAT, LESSP, LESSP, GREATQP, GREATP,
 741:     NEQUAL, 0, GREAT, 0, 0, LESS, GREATP, 0, 0, LESSP,
 742:     EQUAL,  NEQUAL, EQUAL,  0, 0, NEQUAL, EQUAL, 0, 0, NEQUAL,
 743: };
 744: 
 745: xlongrel(f)
 746: {
 747:     register int op, bno;
 748: 
 749:     op = xop;
 750:     if (f==0) {
 751:         if (bno = lrtab[xzero][0][op-EQUAL])
 752:             branch(xlab1, bno, 0);
 753:         if (bno = lrtab[xzero][1][op-EQUAL]) {
 754:             xlab2 = isn++;
 755:             branch(xlab2, bno, 0);
 756:         }
 757:         if (lrtab[xzero][2][op-EQUAL]==0)
 758:             return(1);
 759:     } else {
 760:         branch(xlab1, lrtab[xzero][2][op-EQUAL], 0);
 761:         if (xlab2)
 762:             label(xlab2);
 763:     }
 764:     return(0);
 765: }
 766: 
 767: label(l)
 768: {
 769:     printf("L%d:", l);
 770: }
 771: 
 772: popstk(a)
 773: {
 774:     switch(a) {
 775: 
 776:     case 0:
 777:         return;
 778: 
 779:     case 2:
 780:         printf("tst	(sp)+\n");
 781:         return;
 782: 
 783:     case 4:
 784:         printf("cmp	(sp)+,(sp)+\n");
 785:         return;
 786:     }
 787:     printf("add	$%o,sp\n", UNS(a));
 788: }
 789: 
 790: werror(s)
 791: char *s;
 792: {
 793: 
 794:     fprintf(stderr, "%d: %s\n",line,s);
 795: }
 796: 
 797: /* VARARGS1 */
 798: error(s, p1, p2, p3, p4, p5, p6)
 799: char *s;
 800: {
 801: 
 802:     nerror++;
 803:     fprintf(stderr, "%d: ", line);
 804:     fprintf(stderr, s, p1, p2, p3, p4, p5, p6);
 805:     putc('\n', stderr);
 806: }
 807: 
 808: psoct(an)
 809: {
 810:     register int n;
 811:     register char *sign;
 812: 
 813:     sign = "";
 814:     if ((n = an) < 0) {
 815:         n = -n;
 816:         sign = "-";
 817:     }
 818:     printf("%s%o", sign, n);
 819: }
 820: 
 821: /*
 822:  * Read in an intermediate file.
 823:  */
 824: #define STKS    100
 825: getree()
 826: {
 827:     union tree *expstack[STKS], **sp;
 828:     register union tree *tp;
 829:     register int t, op;
 830:     char s[80];     /* big for asm() stuff & long variable names */
 831:     struct swtab *swp;
 832:     long outloc;
 833:     int lbl, cond, lbl2, lbl3;
 834:     double atof();
 835: 
 836:     curbase = funcbase;
 837:     sp = expstack;
 838:     for (;;) {
 839:         if (sp >= &expstack[STKS])
 840:             error("Stack overflow botch");
 841:         op = geti();
 842:         if ((op&0177400) != 0177000) {
 843:             error("Intermediate file error");
 844:             exit(1);
 845:         }
 846:         lbl = 0;
 847:         switch(op &= 0377) {
 848: 
 849:     case SINIT:
 850:         printf("%o\n", UNS(geti()));
 851:         break;
 852: 
 853:     case EOFC:
 854:         return;
 855: 
 856:     case BDATA:
 857:         if (geti() == 1) {
 858:             printf(".byte ");
 859:             for (;;)  {
 860:                 printf("%o", UNS(geti()));
 861:                 if (geti() != 1)
 862:                     break;
 863:                 printf(",");
 864:             }
 865:             printf("\n");
 866:         }
 867:         break;
 868: 
 869:     case PROG:
 870:         printf(".text\n");
 871:         break;
 872: 
 873:     case DATA:
 874:         printf(".data\n");
 875:         break;
 876: 
 877:     case BSS:
 878:         printf(".bss\n");
 879:         break;
 880: 
 881:     case SYMDEF:
 882:         outname(s);
 883:         printf(".globl\t%s\n", s);
 884:         sfuncr.nloc = 0;
 885:         break;
 886: 
 887:     case RETRN:
 888:         printf("jmp\tcret\n");
 889:         break;
 890: 
 891:     case CSPACE:
 892:         outname(s);
 893:         printf(".comm\t%s,%o\n", s, UNS(geti()));
 894:         break;
 895: 
 896:     case SSPACE:
 897:         printf(".=.+%o\n", UNS(t=geti()));
 898:         totspace += (unsigned)t;
 899:         break;
 900: 
 901:     case EVEN:
 902:         printf(".even\n");
 903:         break;
 904: 
 905:     case SAVE:
 906:         printf("jsr	r5,csv\n");
 907:         break;
 908: 
 909:     case SETSTK:
 910:         t = geti();
 911:         if (t==2)
 912:             printf("tst	-(sp)\n");
 913:         else if (t != 0)
 914:             printf("sub	$%o,sp\n", UNS(t));
 915:         break;
 916: 
 917:     case PROFIL:
 918:         t = geti();
 919:         outname(s);
 920:         printf("mov	$L%d,r0\njsr	pc,mcount\n", t);
 921:         printf(".data\nL%d:%s+1\n.text\n", t, s);
 922:         break;
 923: 
 924:     case ASSEM:
 925:         outname(s);
 926:         printf("%s\n", s);
 927:         break;
 928: 
 929:     case SNAME:
 930:         outname(s);
 931:         printf("~%s=L%d\n", s+1, geti());
 932:         break;
 933: 
 934:     case ANAME:
 935:         outname(s);
 936:         printf("~%s=%o\n", s+1, UNS(geti()));
 937:         break;
 938: 
 939:     case RNAME:
 940:         outname(s);
 941:         printf("~%s=r%d\n", s+1, geti());
 942:         break;
 943: 
 944:     case SWIT:
 945:         t = geti();
 946:         line = geti();
 947:         curbase = funcbase;
 948:         while(swp=(struct swtab *)getblk(sizeof(*swp)), swp->swlab = geti())
 949:             swp->swval = geti();
 950:         pswitch((struct swtab *)funcbase, swp, t);
 951:         break;
 952: 
 953:     case C3BRANCH:      /* for fortran [sic] */
 954:         lbl = geti();
 955:         lbl2 = geti();
 956:         lbl3 = geti();
 957:         goto xpr;
 958: 
 959:     case CBRANCH:
 960:         lbl = geti();
 961:         cond = geti();
 962: 
 963:     case EXPR:
 964:     xpr:
 965:         line = geti();
 966:         if (sp != &expstack[1]) {
 967:             error("Expression input botch");
 968:             exit(1);
 969:         }
 970:         --sp;
 971:         regpanic = 0;
 972:         if (setjmp(jmpbuf)) {
 973:             regpanic = 10;
 974:             fseek(stdout, outloc, 0);
 975:         }
 976:         nstack = 0;
 977:         panicposs = 0;
 978:         *sp = tp = optim(*sp);
 979:         if (regpanic==0 && panicposs)
 980:             outloc = ftell(stdout);
 981:         if (op==CBRANCH)
 982:             cbranch(tp, lbl, cond, 0);
 983:         else if (op==EXPR)
 984:             rcexpr(tp, efftab, 0);
 985:         else {
 986:             if (tp->t.type==LONG || tp->t.type==UNLONG) {
 987:                 rcexpr(tnode(RFORCE, tp->t.type, tp, TNULL), efftab, 0);
 988:                 printf("ashc	$0,r0\n");
 989:             } else {
 990:                 rcexpr(tp, cctab, 0);
 991:                 if (isfloat(tp))
 992:                     printf("cfcc\n");
 993:             }
 994:             printf("jgt	L%d\n", lbl3);
 995:             printf("jlt	L%d\njbr	L%d\n", lbl, lbl2);
 996:         }
 997:         curbase = funcbase;
 998:         break;
 999: 
1000:     case NAME:
1001:         t = geti();
1002:         if (t==EXTERN) {
1003:             tp = getblk(sizeof(struct xtname));
1004:             tp->t.type = geti();
1005:             outname(s);
1006:             tp->x.name = (char *)getblk(strlen(s) + 1);
1007:             strcpy(tp->x.name, s);
1008:         } else {
1009:             tp = getblk(sizeof(struct tname));
1010:             tp->t.type = geti();
1011:             tp->n.nloc = geti();
1012:         }
1013:         tp->t.op = NAME;
1014:         tp->n.class = t;
1015:         tp->n.regno = 0;
1016:         tp->n.offset = 0;
1017:         *sp++ = tp;
1018:         break;
1019: 
1020:     case CON:
1021:         t = geti();
1022:         *sp++ = tconst(geti(), t);
1023:         break;
1024: 
1025:     case LCON:
1026:         geti(); /* ignore type, assume long */
1027:         t = geti();
1028:         op = geti();
1029:         if (t==0 && op>=0 || t == -1 && op<0) {
1030:             *sp++ = tnode(ITOL, LONG, tconst(op, INT), TNULL);
1031:             break;
1032:         }
1033:         tp = getblk(sizeof(struct lconst));
1034:         tp->t.op = LCON;
1035:         tp->t.type = LONG;
1036:         tp->l.lvalue = ((long)t<<16) + UNS(op); /* nonportable */
1037:         *sp++ = tp;
1038:         break;
1039: 
1040:     case FCON:
1041:         t = geti();
1042:         outname(s);
1043:         tp = getblk(sizeof(struct ftconst));
1044:         tp->t.op = FCON;
1045:         tp->t.type = t;
1046:         tp->f.value = isn++;
1047:         tp->f.fvalue = atof(s);
1048:         *sp++ = tp;
1049:         break;
1050: 
1051:     case FSEL:
1052:         tp = tnode(FSEL, geti(), *--sp, TNULL);
1053:         t = geti();
1054:         tp->t.tr2 = tnode(COMMA, INT, tconst(geti(), INT), tconst(t, INT));
1055:         if (tp->t.tr2->t.tr1->c.value==16)
1056:             tp = paint(tp->t.tr1, tp->t.type);
1057:         *sp++ = tp;
1058:         break;
1059: 
1060:     case STRASG:
1061:         tp = getblk(sizeof(struct fasgn));
1062:         tp->t.op = STRASG;
1063:         tp->t.type = geti();
1064:         tp->F.mask = geti();
1065:         tp->t.tr1 = *--sp;
1066:         tp->t.tr2 = NULL;
1067:         *sp++ = tp;
1068:         break;
1069: 
1070:     case NULLOP:
1071:         *sp++ = tnode(0, 0, TNULL, TNULL);
1072:         break;
1073: 
1074:     case LABEL:
1075:         label(geti());
1076:         break;
1077: 
1078:     case NLABEL:
1079:         outname(s);
1080:         printf("%s:\n", s);
1081:         break;
1082: 
1083:     case RLABEL:
1084:         outname(s);
1085:         printf("%s:\n~~%s:\n", s, s+1);
1086:         break;
1087: 
1088:     case BRANCH:
1089:         branch(geti(), 0, 0);
1090:         break;
1091: 
1092:     case SETREG:
1093:         nreg = geti()-1;
1094:         break;
1095: 
1096:     default:
1097:         if (opdope[op]&BINARY) {
1098:             if (sp < &expstack[1]) {
1099:                 error("Binary expression botch");
1100:                 exit(1);
1101:             }
1102:             tp = *--sp;
1103:             *sp++ = tnode(op, geti(), *--sp, tp);
1104:         } else
1105:             sp[-1] = tnode(op, geti(), sp[-1], TNULL);
1106:         break;
1107:     }
1108:     }
1109: }
1110: 
1111: geti()
1112: {
1113:     register short i;
1114: 
1115:     i = getchar() & 0xff;
1116:     i |= (getchar() & 0xff) << 8;
1117:     return(i);
1118: }
1119: 
1120: static
1121: outname(s)
1122: register char *s;
1123: {
1124:     register int c;
1125: 
1126:     while (c = getchar())
1127:         *s++ = c;
1128:     *s++ = '\0';
1129: }
1130: 
1131: strasg(atp)
1132: union tree *atp;
1133: {
1134:     register union tree *tp;
1135:     register nwords, i;
1136: 
1137:     nwords = atp->F.mask/sizeof(short);
1138:     tp = atp->t.tr1;
1139:     while (tp->t.op == SEQNC) {
1140:         rcexpr(tp->t.tr1, efftab, 0);
1141:         tp = tp->t.tr2;
1142:     }
1143:     if (tp->t.op != ASSIGN) {
1144:         if (tp->t.op==RFORCE) { /* function return */
1145:             if (sfuncr.nloc==0) {
1146:                 sfuncr.nloc = isn++;
1147:                 printf(".bss\nL%d:.=.+%o\n.text\n", sfuncr.nloc,
1148:                     UNS(nwords*sizeof(short)));
1149:             }
1150:             atp->t.tr1 = tnode(ASSIGN, STRUCT, (union tree *)&sfuncr, tp->t.tr1);
1151:             strasg(atp);
1152:             printf("mov	$L%d,r0\n", sfuncr.nloc);
1153:             return;
1154:         }
1155:         if (tp->t.op==CALL) {
1156:             rcexpr(tp, efftab, 0);
1157:             return;
1158:         }
1159:         error("Illegal structure operation");
1160:         return;
1161:     }
1162:     tp->t.tr2 = strfunc(tp->t.tr2);
1163:     if (nwords==1)
1164:         paint(tp, INT);
1165:     else if (nwords==sizeof(short))
1166:         paint(tp, LONG);
1167:     else {
1168:         if (tp->t.tr1->t.op!=NAME && tp->t.tr1->t.op!=STAR
1169:          || tp->t.tr2->t.op!=NAME && tp->t.tr2->t.op!=STAR) {
1170:             error("unimplemented structure assignment");
1171:             return;
1172:         }
1173:         tp->t.tr1 = tnode(AMPER, STRUCT+PTR, tp->t.tr1, TNULL);
1174:         tp->t.tr2 = tnode(AMPER, STRUCT+PTR, tp->t.tr2, TNULL);
1175:         tp->t.op = STRSET;
1176:         tp->t.type = STRUCT+PTR;
1177:         tp = optim(tp);
1178:         rcexpr(tp, efftab, 0);
1179:         if (nwords < 7) {
1180:             for (i=0; i<nwords; i++)
1181:                 printf("mov	(r1)+,(r0)+\n");
1182:             return;
1183:         }
1184:         if (nreg<=1)
1185:             printf("mov	r2,-(sp)\n");
1186:         printf("mov	$%o,r2\n", UNS(nwords));
1187:         printf("L%d:mov	(r1)+,(r0)+\ndec\tr2\njne\tL%d\n", isn, isn);
1188:         isn++;
1189:         if (nreg<=1)
1190:             printf("mov	(sp)+,r2\n");
1191:         return;
1192:     }
1193:     rcexpr(tp, efftab, 0);
1194: }
1195: 
1196: /*
1197:  * Reduce the degree-of-reference by one.
1198:  * e.g. turn "ptr-to-int" into "int".
1199:  */
1200: decref(t)
1201: register t;
1202: {
1203:     if ((t & ~TYPE) == 0) {
1204:         error("Illegal indirection");
1205:         return(t);
1206:     }
1207:     return(((unsigned)t>>TYLEN) & ~TYPE | t&TYPE);
1208: }
1209: 
1210: /*
1211:  * Increase the degree of reference by
1212:  * one; e.g. turn "int" to "ptr-to-int".
1213:  */
1214: incref(t)
1215: {
1216:     return(((t&~TYPE)<<TYLEN) | (t&TYPE) | PTR);
1217: }

Defined functions

arlength defined in line 308; used 1 times
branch defined in line 650; used 7 times
breq defined in line 447; used 2 times
cbranch defined in line 560; used 13 times
collcon defined in line 240; used 2 times
dcalc defined in line 140; used 7 times
decref defined in line 1200; never used
degree defined in line 7; used 22 times
error defined in line 798; used 15 times
geti defined in line 1111; used 42 times
getree defined in line 825; used 2 times
incref defined in line 1214; never used
isfloat defined in line 260; used 12 times
ispow2 defined in line 487; used 5 times
label defined in line 767; used 6 times
longrel defined in line 667; used 1 times
notcompat defined in line 181; used 2 times
oddreg defined in line 273; used 2 times
outname defined in line 1120; used 11 times
pbase defined in line 113; used 2 times
pname defined in line 32; used 3 times
popstk defined in line 772; used 1 times
pow2 defined in line 500; used 4 times
prins defined in line 212; used 2 times
psoct defined in line 808; used 3 times
pswitch defined in line 366; used 1 times
sort defined in line 456; used 1 times
strasg defined in line 1131; used 2 times
werror defined in line 790; never used
xdcalc defined in line 123; used 4 times
xlongrel defined in line 745; used 1 times

Defined variables

dirsw defined in line 342; used 1 times
hashsw defined in line 351; used 1 times
lrtab defined in line 735; used 4 times

Defined macros

STKS defined in line 824; used 2 times
Last modified: 1993-06-03
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 6309
Valid CSS Valid XHTML 1.0 Strict