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