home *** CD-ROM | disk | FTP | other *** search
/ SPACE 2 / SPACE - Library 2 - Volume 1.iso / program / 332 / hcc / gen.c < prev    next >
Encoding:
C/C++ Source or Header  |  1989-08-26  |  12.4 KB  |  699 lines

  1. /* Copyright (c) 1988 by Sozobon, Limited.  Author: Johann Ruegg
  2.  *
  3.  * Permission is granted to anyone to use this software for any purpose
  4.  * on any computer system, and to redistribute it freely, with the
  5.  * following restrictions:
  6.  * 1) No charge may be made other than reasonable charges for reproduction.
  7.  * 2) Modified versions must be clearly marked as such.
  8.  * 3) The authors are not responsible for any harmful consequences
  9.  *    of using this software, even if they result from defects in it.
  10.  *
  11.  *    gen.c
  12.  *
  13.  *    Generate code.
  14.  *    Includes main routine and code generation for unary nodes
  15.  *    and leafs.
  16.  */
  17.  
  18. #include <stdio.h>
  19. #include "param.h"
  20. #include "bstok.h"
  21. #include "tytok.h"
  22. #include "flags.h"
  23. #include "nodes.h"
  24. #include "gen.h"
  25.  
  26. NODEP strsave;
  27. int cctest;
  28. static int reserve;
  29. static int tmpused;
  30.  
  31. extern xflags[];
  32. #define debug xflags['g'-'a']
  33.  
  34. #define FAIL    0
  35. #define OKAY    1
  36.  
  37. #define isimmed(np)    ((np)->g_flags & IMMEDID)
  38. #define isareg(np)    ((np)->g_token == REGVAR && (np)->g_rno >= AREG)
  39. #define isdreg(np)    ((np)->g_token == REGVAR && (np)->g_rno < AREG)
  40. #define istdreg(np)    ((np)->g_token == REGVAR && (np)->g_rno < DRV_START)
  41.  
  42. int cookflags[] = {
  43.     0,
  44.     NOVAL_OK|CC_OK|IMMA_OK,        /* FORSIDE */
  45.     IMMA_OK,            /* FORPUSH */
  46.     CC_OK,                /* FORCC */
  47.     IMMA_OK,            /* FORIMA */
  48.     0,                /* FORADR */
  49.     IMMA_OK,            /* FORINIT */
  50.     0,                /* IND0 */
  51.     0,                /* RETSTRU */
  52. };
  53.  
  54. genx(np, cookie)
  55. register NODEP np;
  56. {
  57.     extern nmerrors;
  58.     int rv;
  59.     extern NODE *blktab;
  60.  
  61.     if (np == NULL) return;
  62.     if (nmerrors)
  63.         goto bad;
  64.     if (debug) {
  65.         printf("GEN enter");
  66.         printnode(np);
  67.     }
  68.  
  69.     untype(np);
  70.     if (debug>1) {
  71.         printf("after UNTYPE");
  72.         printnode(np);
  73.     }
  74.  
  75.     tmpused = 0;
  76.     gunk(np);
  77.     if (tmpused && tmpused > blktab->b_tsize)
  78.         blktab->b_tsize = tmpused;
  79.     if (debug > 1) {
  80.         printf("after gunk");
  81.         printnode(np);
  82.     }
  83.     order(np);
  84.  
  85.     reserve = 0;
  86.     rv = eval(np, cookie);
  87.     if (rv == OKAY && debug) {
  88.         printf("GEN exit");
  89.         codeprint(np);
  90.     }
  91.     if (rv == OKAY)
  92.         rv = cookmon(np, cookie);
  93.     else
  94.         error("couldnt eval node");
  95.     freenode(np);
  96.     return rv;
  97. bad:
  98.     freenode(np);
  99.     return FAIL;
  100. }
  101.  
  102. eval(np, cookie)
  103. register NODEP np;
  104. {
  105.     int rv;
  106.  
  107.     np->g_r1 = np->g_r2 = -1;
  108.  
  109.     if (np == NULL) return FAIL;
  110.  
  111.     switch (np->g_type) {
  112.  
  113.     default:
  114.         rv = b_eval(np, cookie);
  115.         /* already did freetmps */
  116.         free1(np, np->n_left);
  117.         free1(np, np->n_right);
  118.         break;
  119.  
  120.     case EV_LEFT:
  121.         rv = u_eval(np, cookie);
  122.         freetmps(np);
  123.         free1(np, np->n_left);
  124.         break;
  125.  
  126.     case EV_NONE:
  127.         rv = l_eval(np);
  128.         break;
  129.     }
  130.     return rv;
  131. }
  132.  
  133. u_eval(np, cookie)
  134. register NODEP np;
  135. {
  136.     int subcook = FORADR;
  137.  
  138.     switch (np->g_token) {
  139.     case STAR:
  140.         subcook = FORIMA;
  141.         break;
  142.     case '!':
  143.         subcook = FORCC;
  144.         break;
  145.     }
  146.  
  147.     if (eval(np->n_left, subcook) == FAIL)
  148.         return FAIL;
  149.     return u_sube(np, cookflags[cookie]);
  150. }
  151.  
  152. u_sube(np, flags)
  153. register NODEP np;
  154. {
  155.     register NODEP lp = np->n_left;
  156.     long offs;
  157.     int i;
  158.  
  159.     switch (np->g_token) {
  160.     case '.':
  161.         if (np->g_fldw)
  162.             return fldget(np, flags);
  163.         offs = np->g_offs;
  164.         inherit(np);
  165.         np->g_offs += offs;
  166.         return OKAY;
  167.     case STAR:
  168.         if (isimmed(lp)) {
  169.             inherit(np);
  170.             np->g_flags &= ~IMMEDID;
  171.         } else if (isareg(lp)) {
  172.             indir(np, lp->g_rno);
  173.         } else {    /* NEED A temp */
  174.             if (lp->g_token == OREG && istemp(lp->g_rno))
  175.                 i = lp->g_rno;
  176.             else
  177.                 i = ralloc(AREG);
  178.             addcode(np, "\tmove.l\t<A,R0\n");
  179.             indir(np, i);
  180.         }
  181.         return OKAY;
  182.     case UNARY '&':
  183.         if (isimmed(lp))
  184.             warn("& ignored");
  185.         else if (lp->g_token == REGVAR)
  186.             return FAIL;
  187.         inherit(np);
  188.         np->g_flags |= IMMEDID;
  189.         if ((flags & IMMA_OK) == 0)
  190.             imm_oreg(np);
  191.         return OKAY;
  192.     case '~':
  193.         utemp(np);
  194.         addcode(np, "\tnot.S\tA\n");
  195.         cc_hack(np);
  196.         return OKAY;
  197.     case UNARY '-':
  198.         utemp(np);
  199.         addcode(np, "\tneg.S\tA\n");
  200.         cc_hack(np);
  201.         return OKAY;
  202.     case TCONV:
  203.         castgen(np);
  204.         return OKAY;
  205.     case PUSHER:    /* must not be on left of assign or asn-op */
  206.         if ((lp->g_token != OREG && lp->g_token != REGVAR) ||
  207.             istemp(lp->g_rno) == 0) {
  208.             inherit(np);
  209.             return OKAY;
  210.         }
  211.         if (lp->g_ty == ET_A)
  212.             strxpush(np);
  213.         else
  214.             addcode(np, "\tmove.S\t<A,-(sp)\n");
  215.         return OKAY;
  216.     case '(':
  217.         if (np->g_ty == ET_A) {        /* struct returned */
  218.             frc_ral(AREG);
  219.             indir(np, AREG);
  220.         } else {
  221.             frc_ral(0);
  222.             retreg(np, 0);
  223.         }
  224.         addcode(np, "\tjsr\t<A\n");
  225.         return OKAY;
  226.     case DOUBLE '+':
  227.         holdcon(np);
  228.         inherit(np);
  229.         addcode(np, "\tadd.S\t#K,A\n");
  230.         cc_hack(np);
  231.         return OKAY;
  232.     case DOUBLE '-':
  233.         holdcon(np);
  234.         inherit(np);
  235.         addcode(np, "\tsub.S\t#K,A\n");
  236.         cc_hack(np);
  237.         return OKAY;
  238.     case POSTINC:
  239.         if ((flags & NOVAL_OK) == 0) {
  240.             i = ralloc(0);
  241.             retreg(np, i);
  242.             addcode(np, "\tmove.S\t<A,A\n");
  243.         }
  244.         addcode(np, "\tadd.S\t#O,<A\n");
  245.         return OKAY;
  246.     case POSTDEC:
  247.         if ((flags & NOVAL_OK) == 0) {
  248.             i = ralloc(0);
  249.             retreg(np, i);
  250.             addcode(np, "\tmove.S\t<A,A\n");
  251.         }
  252.         addcode(np, "\tsub.S\t#O,<A\n");
  253.         return OKAY;
  254.     case CMPBR:
  255.         i = ralloc(0);
  256.         retreg(np, i);
  257.         addcode(np, "\tsN\tA\n\tand.w\t#1,A\n");
  258.         cc_hack(np);
  259.         return OKAY;
  260.     case '!':
  261.         if (flags & CC_OK) {
  262.             if (iscc(lp)) {
  263.                 i = cctok(lp);
  264.                 i = (i&1) ? i+1 : i-1;    /* reverse truth */
  265.             } else {
  266.                 i = B_EQ;
  267.                 addcode(np, "<Q");
  268.             }
  269.             np->g_token = i + BR_TOK;
  270.         } else {
  271.             if (istdreg(lp))
  272.                 i = lp->g_rno;
  273.             else
  274.                 i = ralloc(0);
  275.             retreg(np, i);
  276.             if (iscc(lp)) {
  277.                 addcode(np, "<EA\n\tand.w\t#1,A\n");
  278.             } else {
  279.                 addcode(np, "<Q");
  280.                 addcode(np, "\tseq\tA\n\tand.w\t#1,A\n");
  281.             }
  282.         }
  283.         return OKAY;
  284.     default:
  285.         printf("Weird u_eval %s ", np->n_name);
  286.         return FAIL;
  287.     }
  288. }
  289.  
  290. holdcon(np)
  291. NODEP np;
  292. {
  293.     np->g_bsize = np->g_offs;
  294. }
  295.  
  296. retreg(np, rno)
  297. NODEP np;
  298. {
  299.     np->g_token = REGVAR;
  300.     np->g_rno = rno;
  301. }
  302.  
  303. indir(np, rno)
  304. register NODEP np;
  305. {
  306.     np->g_token = OREG;
  307.     np->g_offs = 0;
  308.     np->g_rno = rno;
  309. }
  310.  
  311. inherit(np)
  312. register NODEP np;
  313. {
  314.     NODEP lp = np->n_left;
  315.  
  316.     np->g_token = lp->g_token;
  317.     np->g_offs = lp->g_offs;
  318.     np->g_rno = lp->g_rno;
  319.     np->g_flags |= CHILDNM | (lp->g_flags & IMMEDID);
  320. }
  321.  
  322. cookmon(np, cookie)
  323. register NODEP np;
  324. {
  325.     extern FILE *output;
  326.  
  327.     if (np == NULL) return FAIL;
  328.  
  329.     switch (cookie) {
  330.     case FORCC:
  331.         if (iscc(np)) {
  332.             outcode(np);
  333.             cctest = cctok(np);
  334.         } else {
  335.             if (np->g_token == ICON && isimmed(np)) {
  336.                 cctest = np->g_offs ? B_YES : B_NO;
  337.                 return OKAY;
  338.             }
  339.             outcode(np);
  340.             outsub("Q", np);
  341.             cctest = B_NE;
  342.         }
  343.         return OKAY;
  344.     case FORINIT:
  345.         if (anycode(np) == 0 && (np->g_flags & IMMEDID)) {
  346.             out_a(np, output);
  347.             return OKAY;
  348.         }
  349.         error("bad INIT expr");
  350.         return FAIL;
  351.     case IND0:
  352.         outcode(np);
  353.         if (np->g_token != REGVAR ||
  354.             np->g_rno != 0)
  355.             if (np->g_token == ICON && np->g_offs == 0 &&
  356.                 isimmed(np))
  357.                 outsub("\tclr.S\td0\n", np);
  358.             else
  359.                 outsub("\tmove.S\tA,d0\n", np);
  360.         return OKAY;
  361.     case RETSTRU:
  362.         freetmps(np);
  363.         strret(np);
  364.         outcode(np);
  365.         return OKAY;
  366.     }
  367.     outcode(np);
  368.     return OKAY;
  369. }
  370.  
  371. anycode(np)
  372. register NODEP np;
  373. {
  374.     if (np->g_code)
  375.         return 1;
  376.     switch (np->g_type) {
  377.     case EV_NONE:
  378.         return 0;
  379.     case EV_LEFT:
  380.         return anycode(np->n_left);
  381.     case EV_RIGHT:
  382.         return anycode(np->n_right);
  383.     case EV_LR:
  384.     case EV_RL:
  385.         return anycode(np->n_left) || anycode(np->n_right);
  386.     }
  387. }
  388.  
  389. l_eval(np)
  390. register NODEP np;
  391. {
  392.     int l1;
  393.  
  394.     switch (np->g_token) {
  395.     case ID:
  396.         switch (np->g_sc) {
  397.         default:    /* EXTERN or HERE */
  398.             np->g_token = ONAME;
  399.             np->g_offs = 0;
  400.             if (np->n_name[0] != '%')
  401.                 nnmins(np, "_");
  402.             else    /* hack for inline name */
  403.                 strcpy(np->n_name, &np->n_name[1]);
  404.             return OKAY;        /* dont free n_nmx */
  405.         case K_STATIC:
  406.             sprintf(np->n_name, "L%d", (int)np->g_offs);
  407.             np->g_offs = 0;
  408.             np->g_token = ONAME;
  409.             break;
  410.         case K_AUTO:
  411.             np->g_rno = FRAMEP;
  412.             np->g_token = OREG;
  413.             break;
  414.         case K_REGISTER:
  415.             np->g_token = REGVAR;
  416.             break;
  417.         }
  418.         if (np->n_nmx) {
  419.             freenode(np->n_nmx);
  420.             np->n_nmx = NULL;
  421.         }
  422.         return OKAY;
  423.     case ICON:
  424.         np->g_flags |= IMMEDID;
  425.         return OKAY;
  426.     case FCON:
  427.         np->g_flags |= IMMEDID;
  428.         return OKAY;
  429.     case SCON:
  430.         np->g_flags |= IMMEDID;
  431.         np->g_token = ONAME;
  432.         l1 = new_lbl();
  433.         save_scon(np, l1);
  434.         sprintf(np->n_name, "L%d", l1);
  435.         return OKAY;
  436.     case OREG:
  437.         return OKAY;
  438.     }
  439.     return FAIL;
  440. }
  441.  
  442. save_scon(np, lbl)
  443. NODEP np;
  444. {
  445.     NODEP tp, copyone();
  446.  
  447.     tp = copyone(np);
  448.     tp->g_offs = lbl;
  449.     if (np->n_nmx) {
  450.         freenode(np->n_nmx);
  451.         np->n_nmx = NULL;
  452.     }
  453.     putlist(&strsave, tp);
  454. }
  455.  
  456. utemp(np)
  457. NODEP np;
  458. {
  459.     NODEP lp = np->n_left;
  460.     int i;
  461.  
  462.     if (lp->g_token == REGVAR && 
  463.         istemp(lp->g_rno)) {
  464.         inherit(np);
  465.         return;
  466.     }
  467.     i = ralloc(0);
  468.     retreg(np, i);
  469.     addcode(np, "\tmove.S\t<A,A\n");
  470. }
  471.  
  472. freetmps(np)
  473. register NODEP np;
  474. {
  475.     if (np->g_r1 != -1)
  476.         rfree(np->g_r1);
  477.     if (np->g_r2 != -1)
  478.         rfree(np->g_r2);
  479. }
  480.  
  481. free1(np, cp)
  482. NODEP np, cp;
  483. {
  484.     int cr;
  485.  
  486.     if (cp->g_token != OREG && cp->g_token != REGVAR)
  487.         return;
  488.     cr = cp->g_rno;
  489.     if (np && cr == np->g_rno &&
  490.         (np->g_token == OREG || np->g_token == REGVAR))
  491.         return;
  492.     if (istemp(cr))
  493.         rfree(cr);
  494. }
  495.  
  496. istemp(rno)
  497. {
  498.     return (rno < DRV_START || 
  499.         (rno >= AREG && rno < ARV_START));
  500. }
  501.  
  502. rfree(rno)
  503. {
  504.     reserve &= ~(1<<rno);
  505. }
  506.  
  507. frc_ral(rno)
  508. {
  509.     int i;
  510.  
  511.     i = (1<<rno);
  512.     if (reserve & i)
  513.         error("rno reserved! ");
  514.     reserve |= i;
  515. }
  516.  
  517. tempr(np, type)
  518. NODEP np;
  519. {
  520.     int i;
  521.  
  522.     i = ralloc(type);
  523.     if (np->g_r1 == -1)
  524.         np->g_r1 = i;
  525.     else
  526.         np->g_r2 = i;
  527.     return i;
  528. }
  529.  
  530. ralloc(type)
  531. {
  532.     int starti, endi;
  533.     register int i;
  534.  
  535.     if (type == AREG) {
  536.         starti = AREG;
  537.         endi = ARV_START;
  538.     } else {
  539.         starti = 0;
  540.         endi = DRV_START;
  541.     }
  542.     for (i=starti; i<endi; i++)
  543.         if ((reserve & (1<<i)) == 0) {
  544.             reserve |= (1<<i);
  545.             return i;
  546.         }
  547.     error("Compiler failure - rallo");
  548.     return -1;
  549. }
  550.  
  551. tmp_alloc(sz)
  552. {
  553.     extern NODE *blktab;
  554.  
  555.     tmpused += sz;
  556.     return blktab->b_size + tmpused;
  557. }
  558.  
  559. /* fixes nodes with no code or aX is temp that are #d(aX) */
  560. imm_oreg(np)
  561. NODEP np;
  562. {
  563.     char *regnm(), buf[30];
  564.     int i;
  565.  
  566.     if (np->g_token != OREG)
  567.         return;
  568.     if ((np->g_flags & IMMEDID) == 0)
  569.         return;
  570.     np->g_flags &= ~IMMEDID;
  571.     if (np->g_offs == 0) {        /* #(a0) -> a0 */
  572.         np->g_token = REGVAR;
  573.         return;
  574.     }
  575.     if (istemp(np->g_rno)) {
  576.         holdcon(np);
  577.         addcode(np, "\tadd\t#K,A\n");
  578.         np->g_token = REGVAR;
  579.         return;
  580.     }
  581.     sprintf(buf, "\tlea\t%d(%s),A\n", (int)np->g_offs, regnm(np->g_rno));
  582.     addcode(np, buf);
  583.     i = ralloc(AREG);
  584.     retreg(np, i);
  585. }
  586.  
  587. castgen(tp)
  588. register NODEP tp;
  589. {
  590.     register NODEP np = tp->n_left;
  591.     int sz = tp->g_sz;
  592.     int i;
  593.  
  594.     if (np->g_token == ICON && isimmed(np)) {
  595.         if (tp->g_ty == ET_F) {
  596.             tp->g_token = FCON;
  597.             *(float *)&tp->g_offs = (float)np->g_offs;
  598.             tp->g_flags |= IMMEDID;
  599.         } else {
  600.             inherit(tp);
  601.             i_exp(tp, np->g_sz, np->g_ty);
  602.             squish(tp);
  603.         }
  604.     } else if (np->g_token == FCON && isimmed(np)) {
  605.         if (tp->g_ty != ET_F) {
  606.             tp->g_token = ICON;
  607.             tp->g_offs = (long)*(float *)&np->g_offs;
  608.             tp->g_flags |= IMMEDID;
  609.             squish(tp);
  610.         } else {
  611.             inherit(tp);
  612.         }
  613.     } else if (sz > np->g_sz) {
  614.         if (np->g_ty == ET_U) {
  615.             i = ralloc(0);
  616.             retreg(tp, i);
  617.             addcode(tp, "\tclr.S\tA\n\tmove.<S\t<A,A\n");
  618.         } else {
  619.             if (isdreg(np)) {
  620.                 inherit(tp);
  621.             } else {
  622.                 i = ralloc(0);
  623.                 retreg(tp, i);
  624.                 addcode(tp, "\tmove.<S\t<A,A\n");
  625.             }
  626.             if (sz == 4 && np->g_sz == 1)
  627.                 addcode(tp, "\text.w\tA\n\text.l\tA\n");
  628.             else
  629.                 addcode(tp, "\text.S\tA\n");
  630.         }
  631.         return;
  632.     }
  633.     else if (sz < np->g_sz) {
  634.         switch (np->g_token) {
  635.         case ONAME:
  636.         case OREG:
  637.             if (isimmed(np)) {
  638. smfudge:
  639.                 i = ralloc(0);
  640.                 retreg(tp, i);
  641.                 addcode(tp, "\tmove.<S\t<A,A\n");
  642.                 return;
  643.             }
  644.             inherit(tp);
  645.             tp->g_offs = np->g_offs + (np->g_sz - sz);
  646.             break;
  647.         case REGVAR:
  648.             if (sz == 1 && np->g_rno >= AREG)
  649.                 goto smfudge;
  650.             /* fall through */
  651.         default:
  652.             inherit(tp);
  653.         }
  654.     } else
  655.         inherit(tp);
  656. }
  657.  
  658. squish(np)
  659. NODEP np;
  660. {
  661.     int neg;
  662.  
  663.     neg = (np->g_ty == ET_S && np->g_offs < 0);
  664.  
  665.     switch (np->g_sz) {
  666.     case 1:
  667.         if (neg)
  668.             np->g_offs |= 0xffffff00L;
  669.         else
  670.             np->g_offs &= 0xff;
  671.         break;
  672.     case 2:
  673.         if (neg)
  674.             np->g_offs |= 0xffff0000L;
  675.         else
  676.             np->g_offs &= 0xffffL;
  677.         break;
  678.     }
  679. }
  680.  
  681. i_exp(np, osz, oty)
  682. NODEP np;
  683. {
  684.     long l;
  685.  
  686.     if (oty == ET_S && osz < np->g_sz) {
  687.         l = np->g_offs;
  688.         switch (osz) {
  689.         case 1:
  690.             l = (char) l;
  691.             break;
  692.         case 2:
  693.             l = (short) l;
  694.             break;
  695.         }
  696.         np->g_offs = l;
  697.     }
  698. }
  699.