home *** CD-ROM | disk | FTP | other *** search
/ Crawly Crypt Collection 1 / crawlyvol1.bin / program / compiler / sozobon / scsrc20 / hcc / gsub.c < prev    next >
C/C++ Source or Header  |  1991-02-22  |  10KB  |  549 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.  *    gsub.c
  12.  *
  13.  *    Various code generation subroutines
  14.  *    Includes generation of switches and
  15.  *    conversion of type lists to simple type,size.
  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. #define isimmed(np)    ((np)->g_flags & IMMEDID)
  27. #define isareg(np)    ((np)->g_token == REGVAR && (np)->g_rno >= AREG)
  28.  
  29. extern cctest;
  30.  
  31. extern xflags[];
  32. #define debug    xflags['s'-'a']
  33.  
  34. gen_brt(np, lbl)
  35. NODEP np;
  36. {
  37.     p2_expr(&np);
  38.     mustty(np, R_SCALAR);
  39.     br_sub(np, 0, lbl);
  40. }
  41.  
  42. gen_brf(np, lbl)
  43. NODEP np;
  44. {
  45.     p2_expr(&np);
  46.     mustty(np, R_SCALAR);
  47.     br_sub(np, 1, lbl);
  48. }
  49.  
  50. br_sub(np, rev, lbl)
  51. NODEP np;
  52. {
  53.     int i;
  54.  
  55.     switch (np->e_token) {
  56.         case DOUBLE '&':
  57.             br_split(np, lbl, rev);
  58.             return;
  59.         case DOUBLE '|':
  60.             br_split(np, lbl, 2+rev);
  61.             return;
  62.     }
  63.     genx(np, FORCC);
  64.     i = cctest;
  65.     if (i) {
  66.         if (rev)
  67.             /* reverse truth */
  68.             i = (i&1) ? i+1 : i-1;
  69.         out_b(i, lbl);
  70.     }
  71. }
  72.  
  73. br_split(np, lbl, n)
  74. NODEP np;
  75. {
  76.     int nlbl;
  77.  
  78.     if (n == 0 || n == 3)
  79.         nlbl = new_lbl();
  80.     else
  81.         nlbl = lbl;
  82.  
  83.     br_sub(np->n_left, n<2, nlbl);
  84.     br_sub(np->n_right, n&1, lbl);
  85.  
  86.     freeunit(np);
  87.  
  88.     if (nlbl != lbl)
  89.         def_lbl(nlbl);    
  90. }
  91.  
  92. /* generate switch
  93.     np - list of nodes with value,label pairs (sorted)
  94.     dlbl - default label or -1
  95.  */
  96. #undef min
  97. #undef max
  98.  
  99. gen_switch(np, odlbl)
  100. NODEP np;
  101. {
  102.     int n,min,max;
  103.     int dlbl;
  104.     register NODEP p;
  105.  
  106.     if (debug) {
  107.         printf("gs %d ", odlbl);
  108.         printnode(np);
  109.     }
  110.  
  111.     /* if no default, make one! */
  112.     if (odlbl < 0)
  113.         dlbl = new_lbl();
  114.     else
  115.         dlbl = odlbl;
  116.  
  117.     n = 0;
  118.     for (p=np; p; p=p->n_next) {
  119.         if (n == 0)
  120.             min = max = p->c_casev;
  121.         else
  122.             max = p->c_casev;
  123.         n++;
  124.     }
  125.     if (n <= C_SIMPLE)
  126.         simple_sw(np,odlbl);
  127.     else if (n >= max/C_RATIO - min/C_RATIO)
  128.         table_sw(np,dlbl,min,max);
  129.     else {
  130.         half_sw(np,dlbl,max/2+min/2,n);
  131.         goto out;        /* free already done */
  132.     }
  133.     freenode(np);
  134. out:
  135.     if (odlbl < 0)
  136.         def_lbl(dlbl);
  137. }
  138.  
  139. /* simple if-else type switch
  140.     dlbl may be -1 -> fall through
  141.     does not free np
  142. */
  143. simple_sw(np, dlbl)
  144. register NODEP np;
  145. {
  146.     while (np) {
  147.         out_d0cmp(np->c_casev);
  148.         out_b(B_EQ, np->c_casel);
  149.         np = np->n_next;
  150.     }
  151.     if (dlbl >= 0)
  152.         out_br(dlbl);
  153. }
  154.  
  155. /* use table switch
  156.     dlbl is not -1
  157.     does not free np
  158. */
  159. table_sw(np, dlbl, min, max)
  160. NODEP np;
  161. {
  162.     out_d0cmp(min);
  163.     out_b(B_LT, dlbl);
  164.     out_d0cmp(max);
  165.     out_b(B_GT, dlbl);
  166.     if (min)
  167.         out_d0sub(min);
  168.  
  169.     out_tsw();
  170.  
  171.     while (np) {
  172.         while (min < np->c_casev) {
  173.             out_tlbl(dlbl);
  174.             min++;
  175.         }
  176.         out_tlbl(np->c_casel);
  177.         min++;
  178.         np = np->n_next;
  179.     }
  180. }
  181.  
  182. /* cut switch in half (by value)
  183.     dlbl is not -1
  184.     will free np
  185.  */
  186. half_sw(np, dlbl, cut, n)
  187. NODEP np;
  188. {
  189.     register NODEP p, last;
  190.     int nlo, nhi;
  191.     int l1;
  192.  
  193.     for (p=np; p->c_casev < cut; p = p->n_next)
  194.         last = p;
  195.     /* we KNOW both pieces are non-NULL ! */
  196.     last->n_next = NULL;
  197.     last = p;
  198.  
  199.     nlo = 0;
  200.     nhi = 0;
  201.     for (p=np; p; p=p->n_next)
  202.         nlo++;
  203.     nhi = n - nlo;
  204.     
  205.     if (nhi == 1) {        /* switch hi and low */
  206.         p = np;
  207.         np = last;
  208.         last = p;
  209.         nlo = 1;
  210.         nhi = n-1;
  211.     }
  212.     if (nlo == 1) {        /* also nhi == 1 */
  213.         out_d0cmp(np->c_casev);
  214.         out_b(B_EQ, np->c_casel);
  215.         freenode(np);
  216.         gen_switch(last, dlbl);
  217.         return;
  218.     }
  219.     l1 = new_lbl();
  220.     out_d0cmp(cut);
  221.     out_b(B_GE, l1);
  222.     gen_switch(np, dlbl);
  223.     def_lbl(l1);
  224.     gen_switch(last, dlbl);    
  225. }
  226.  
  227. istempa(np)
  228. register NODEP np;
  229. {
  230.     if (np->g_token == OREG && istemp(np->g_rno))
  231.         return 1;
  232.     return 0;
  233. }
  234.  
  235. char chunkch[] = {0, 'b', 'w', 0, 'l'};
  236.  
  237. strasn(np)
  238. NODEP np;
  239. {
  240.     int r;
  241.     long count, i;
  242.     int chunk, l;
  243.     char buf[40];
  244.     int lisa, risa, rissp;
  245.     int useloop;
  246.  
  247.     if (np->g_ty != ET_A)
  248.         return 0;
  249.  
  250.     count = np->g_bsize;
  251.     chunk = np->g_sz;
  252.     if (count == 1) {
  253.         return 0;
  254.     }
  255.  
  256.     useloop = count > 3;
  257.  
  258.     lisa = istempa(np->n_left);
  259.     risa = istempa(np->n_right);
  260.     rissp = (np->n_right->g_token == PUSHER);
  261.  
  262.     if (lisa)
  263.         r = np->n_left->g_rno;
  264.     else
  265.         r = ralloc(AREG);    /* R0 */
  266.     indir(np, r);
  267.     np->g_offs = -(count*chunk);
  268.  
  269.     if (risa)
  270.         np->g_r1 = np->n_right->g_rno;
  271.     else if (rissp)
  272.         np->g_r1 = AREG+7;
  273.     else
  274.         tempr(np, AREG);    /* R1 */
  275.     if (useloop)
  276.         tempr(np, 0);        /* R2 */
  277.  
  278.     if (!lisa || np->n_left->g_offs)
  279.         addcode(np, "\tlea\t<A,R0\n");
  280.     if (!(risa||rissp) || np->n_right->g_offs)
  281.         addcode(np, "\tlea\t>A,R1\n");
  282.  
  283.     if (useloop) {
  284.         sprintf(buf, "\tmove.w\t#%d,R2\n", (int)(count-1));
  285.         addcode(np, buf);
  286.         l = new_lbl();
  287.         sprintf(buf, "'L%d:\tmove.%c\t(R1)+,(R0)+\n",l,chunkch[chunk]);
  288.         addcode(np, buf);
  289.         sprintf(buf, "\tdbra\tR2,'L%d\n", l);
  290.         addcode(np, buf);
  291.     } else for (i=0; i<count; i++) {
  292.         sprintf(buf, "\tmove.%c\t(R1)+,(R0)+\n", chunkch[chunk]);
  293.         addcode(np, buf);
  294.     }
  295.  
  296.     if (chunk == 1 && count & 1 && rissp)
  297.         addcode(np, "\tmove.b\t(sp)+,R2\n");
  298.         
  299.     return 1;
  300. }
  301.  
  302. strret(np)
  303. NODEP np;
  304. {
  305.     extern funstrl;
  306.  
  307.     strsub(np, funstrl);
  308. }
  309.  
  310. strpush(np)
  311. NODEP np;
  312. {
  313.     return strsub(np, 0);
  314. }
  315.  
  316. strxpush(np)
  317. NODEP np;
  318. {
  319.     strsub(np, -1);
  320. }
  321.  
  322. strsub(np, tolbl)
  323. register NODEP np;
  324. {
  325.     long count, i;
  326.     int chunk, l;
  327.     char buf[40];
  328.     char *frstr;
  329.     register NODEP tp;
  330.     int useloop;
  331.  
  332.     count = np->g_bsize;
  333.     chunk = np->g_sz;
  334.     if (chunk == 1 && count & 1 && tolbl <= 0)
  335.         count++;
  336.  
  337.     useloop = count > 3;
  338.  
  339.     if (useloop && np->g_r2 == -1)
  340.         np->g_r2 = ralloc(0);
  341.  
  342.     /* set up 'from' address */
  343.     if (np->g_token == OREG && istemp(np->g_rno)) {
  344.         frstr = "R0";
  345.         if (np->g_offs)
  346.             addcode(np, "\tlea\tA,R0\n");
  347.     } else if (tolbl == -1 && (tp = np->n_left) &&
  348.         tp->g_token == OREG && istemp(tp->g_rno) &&
  349.         tp->g_offs == 0) {
  350.         frstr = "R1";
  351.         np->g_r1 = tp->g_rno;
  352.     } else {
  353.         frstr = "R1";
  354.         if (np->g_r1 == -1)
  355.             np->g_r1 = ralloc(AREG);
  356.         if (tolbl == -1)
  357.             addcode(np, "\tlea\t<A,R1\n");
  358.         else
  359.             addcode(np, "\tlea\tA,R1\n");
  360.     }
  361.  
  362.     /* set up 'to' address */
  363.     if (tolbl > 0) {
  364.         sprintf(buf, "\tmove.l\t#'L%d,H\n", tolbl);
  365.         addcode(np, buf);
  366.     } else {
  367.         sprintf(buf, "\tsub\t#%d,sp\n", (int)(count*chunk));
  368.         addcode(np, buf);
  369.         addcode(np, "\tmove.l\tsp,H\n");
  370.     }
  371.  
  372.     /* generate copy loop */
  373.     if (useloop) {
  374.         sprintf(buf, "\tmove.w\t#%d,R2\n", (int)(count-1));
  375.         addcode(np, buf);
  376.         l = new_lbl();
  377.         sprintf(buf, "'L%d:\tmove.%c\t(%s)+,(H)+\n", l, chunkch[chunk],
  378.             frstr);
  379.         addcode(np, buf);
  380.         sprintf(buf, "\tdbra\tR2,'L%d\n", l);
  381.         addcode(np, buf);
  382.     } else for (i=0; i<count; i++) {
  383.         sprintf(buf, "\tmove.%c\t(%s)+,(H)+\n", chunkch[chunk],
  384.             frstr);
  385.         addcode(np, buf);
  386.     }
  387.  
  388.     return count*chunk;
  389. }
  390.  
  391. specasn(np, flags)
  392. NODEP np;
  393. {
  394.     NODEP lp = np->n_left, rp = np->n_right;
  395.     int r;
  396.  
  397.     if (rp->g_token == ICON && isimmed(rp)) {
  398.         rinherit(np);
  399.  
  400.         if (rp->g_offs == 0)
  401.             addcode(np, isareg(lp) ? "\tsub.S\t<A,<A\n"
  402.                 : "\tclr.S\t<A\n");
  403.         else
  404.             addcode(np, "\tmove.S\t>A,<A\n");
  405.         return 1;
  406.     }
  407.     if (rp->g_token == OREG && isimmed(rp)) {
  408.         rp->g_flags &= ~IMMEDID;
  409.         if (isareg(lp)) {
  410.             inherit(np);
  411.             addcode(np, "\tlea\t>A,A\n");
  412.         } else if (rp->g_offs == 0) {
  413.             retreg(np, rp->g_rno);
  414.             addcode(np, "\tmove.l\tA,<A\n");
  415.         } else {
  416.             if (istemp(rp->g_rno))
  417.                 r = rp->g_rno;
  418.             else
  419.                 r = ralloc(AREG);
  420.             retreg(np, r);
  421.             addcode(np, "\tlea\t>A,A\n");
  422.             addcode(np, "\tmove.l\tA,<A\n");
  423.         }
  424.         return 1;
  425.     }
  426.     return 0;
  427. }
  428.  
  429. untype(np)
  430. register NODEP np;
  431. {
  432.     if (np == NULL || np->n_tptr == NULL) {
  433.         printf("? NULL untype ");
  434.         return;
  435.     }
  436.     
  437.     switch (np->e_type) {
  438.     case E_BIN:
  439.         untype(np->n_right);
  440.         /* fall through */
  441.     case E_UNARY:
  442.         if (np->e_token == '.' && np->e_fldw) {
  443.             np->g_fldw = np->e_fldw;
  444.             np->g_fldo = np->e_fldo;
  445.         } else
  446.             np->g_fldw = 0;
  447.  
  448.         untype(np->n_left);
  449.     }
  450.  
  451.     get_tyinf(np);
  452.  
  453.     if ((np->n_flags & N_COPYT) == 0)
  454.         freenode(np->n_tptr);
  455.     np->n_tptr = NULL;        /* is g_code */
  456.     np->g_betw = NULL;
  457. }
  458.  
  459. static char bty[] = {
  460.     ET_U, ET_U, ET_S, ET_S, ET_U, ET_S, ET_S, ET_F, ET_F, 0
  461. };
  462.  
  463. static char bsz[] = {
  464.     SIZE_C, SIZE_L, SIZE_L, SIZE_S, SIZE_U,
  465.     SIZE_I, SIZE_C, SIZE_F, SIZE_D, 0
  466. };
  467.  
  468. get_tyinf(np)
  469. register NODEP np;
  470. {
  471.     NODEP tp = np->n_tptr;
  472.     int n;
  473.     long offs;
  474.     double fval;
  475.  
  476.     if (tp->t_token != K_DOUBLE)
  477.         offs = np->e_offs;
  478.     else
  479.         fval = np->e_fval;
  480.  
  481.     /* inherit name,token,left,right,nmx from common
  482.         and token, flags, type, sc from enode */
  483.  
  484.     switch (tp->t_token) {
  485.     case K_STRUCT:
  486.     case K_UNION:
  487.         np->g_ty = ET_A;
  488.         /* determine copy chunk size and number of chunks */
  489.         if (tp->t_aln & 1) {
  490.             if (tp->t_size & 1)
  491.                 fatal("aligned struct with odd size");
  492.             if (tp->t_size & 2) {
  493.                 np->g_bsize = tp->t_size >> 1;
  494.                 np->g_sz = 2;
  495.             } else {
  496.                 np->g_bsize = tp->t_size >> 2;
  497.                 np->g_sz = 4;
  498.             }
  499.         } else {
  500.             np->g_bsize = tp->t_size;
  501.             np->g_sz = 1;
  502.         }
  503.         break;
  504.     case '(':
  505.         break;
  506.     case STAR:
  507.         np->g_ty = ET_U;
  508.         np->g_sz = SIZE_P;
  509.         break;
  510.     default:
  511.         n = tp->t_token-FIRST_BAS;
  512.         np->g_ty = bty[n];
  513.         np->g_sz = bsz[n];
  514.     }
  515.  
  516.     if (tp->t_token != K_DOUBLE)
  517.         np->g_offs = offs;    /* different place */
  518.     else
  519.         np->g_fval = fval;
  520. }
  521.  
  522. addcode(np, s)
  523. register NODEP np;
  524. char *s;
  525. {
  526.     NODEP tp;
  527.     int i, c;
  528.  
  529.     while (np->g_code)
  530.         np = np->g_code;
  531.     tp = allocnode();
  532.     np->g_code = tp;
  533.     np->n_flags &= ~N_COPYT;
  534.     i = strlen(s);
  535.     if (i < NMXSIZE) {    /* fits in one */
  536.         strcpy(tp->n_name, s);
  537.         return;
  538.     }
  539.  
  540.     /* need to split it */
  541.     i = NMXSIZE-1;
  542.     c = s[i-1];
  543.     if (c == '<' || c == '>' || (c>='A' && c<='Z'))    /* special */
  544.         i--;
  545.     strncpy(tp->n_name, s, i);
  546.     tp->n_name[i] = 0;
  547.     addcode(tp, &s[i]);
  548. }
  549.