home *** CD-ROM | disk | FTP | other *** search
/ Crawly Crypt Collection 1 / crawlyvol1.bin / program / compiler / sozobon / scsrc20 / hcc / gen.c < prev    next >
C/C++ Source or Header  |  1991-02-22  |  13KB  |  712 lines

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