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