home *** CD-ROM | disk | FTP | other *** search
/ Crawly Crypt Collection 1 / crawlyvol1.bin / program / compiler / sozobon / scsrc20 / hcc / gunk.c < prev    next >
C/C++ Source or Header  |  1991-02-22  |  16KB  |  942 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.  *    gunk.c
  12.  *
  13.  *    Transformations on expression trees
  14.  *    Most of this stuff is because we cant handle
  15.  *    floats, long mul/div, or fields directly.
  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 copyone();
  27.  
  28. #define gwiden(x)    ((x)==1 ? 2 : (x))
  29. #define isfield(np)    ((np)->g_token == '.' && (np)->g_fldw)
  30.  
  31. NODEP npar1, npar2, npar3;
  32. char *spar1, *spar2, *spar3;
  33. int ipar1, ipar2, ipar3;
  34.  
  35. struct rule {
  36.     int (*match)();        /* test for transformation needed */
  37.     int (*rewri)();        /* rewrite function */
  38. };
  39.  
  40. int m_unfold(), unfold(), m_cast(), cast(), m_inline(), inline();
  41. int m_hardas(), hardas(), m_fcmp(), fcmp(), m_md_shf(), md_shf();
  42. int m_eident(), eident(), m_incdec(), incdec(), m_fldas(), fldas();
  43.  
  44. struct rule gunktbl[] = {
  45.     {m_unfold, unfold},
  46.     {m_cast, cast},
  47.     {m_md_shf, md_shf},
  48.     {m_eident, eident},
  49.     {m_incdec, incdec},
  50.     {m_hardas, hardas},
  51.     {m_inline, inline}, /* must cast before inline */
  52.     {m_fcmp, fcmp},
  53.     {m_fldas, fldas},
  54.     {0}
  55. };
  56.  
  57. int anygunk;
  58.  
  59. gunk(np)
  60. NODEP np;
  61. {
  62.     do {
  63.         anygunk = 0;
  64.         gunks(np);
  65.     } while (anygunk);
  66. }
  67.  
  68. gunks(np)
  69. register NODEP np;
  70. {
  71.     switch (np->g_type) {
  72.     case E_BIN:
  73.         gunks(np->n_right);
  74.     case E_UNARY:
  75.         gunks(np->n_left);
  76.     }
  77.     gunk1(np);
  78. }
  79.  
  80. gunk1(np)
  81. NODEP np;
  82. {
  83.     register struct rule *p;
  84.  
  85.     for (p=gunktbl; p->match; p++)
  86.         if ((*p->match)(np)) {
  87.             anygunk++;
  88.             (*p->rewri)(np);
  89.             return;
  90.         }
  91. }
  92.  
  93. /*
  94.  *    Change pointer arithmetic to equivalent trees
  95.  *        (main thing is to mult or div by object size)
  96.  */
  97. m_unfold(np)
  98. NODEP np;
  99. {
  100.     switch (np->g_token) {
  101.     case PTRADD:
  102.         ipar1 = '+';
  103.         return 1;
  104.     case PTRSUB:
  105.         ipar1 = '-';
  106.         return 1;
  107.     case PTRDIFF:
  108.         ipar1 = 0;
  109.         return 1;
  110.     case ASSIGN PTRADD:
  111.         ipar1 = ASSIGN '+';
  112.         return 1;
  113.     case ASSIGN PTRSUB:
  114.         ipar1 = ASSIGN '-';
  115.         return 1;
  116.     }
  117.     return 0;
  118. }
  119.  
  120. unfold(np)
  121. NODEP np;
  122. {
  123.     if (ipar1) {
  124.         ins_mul(np, np->g_offs);
  125.         np->g_token = ipar1;
  126.     } else {
  127.         ins_div(np, np->g_offs);
  128.     }
  129. }
  130.  
  131. NODEP
  132. newgcon(kon, ty, sz)
  133. long kon;
  134. {
  135.     register NODEP kp;
  136.  
  137.     kp = allocnode();
  138.     kp->g_token = ICON;
  139.     sprintf(kp->n_name, "%ld", kon);
  140.     kp->g_offs = kon;
  141.     kp->g_type = E_LEAF;
  142.     kp->g_ty = ty;
  143.     kp->g_sz = sz;
  144.     return kp;
  145. }
  146.  
  147. ins_mul(np, kon)
  148. NODEP np;
  149. long kon;
  150. {
  151.     NODEP rp = np->n_right;
  152.     register NODEP mp, kp;
  153.  
  154.     if (kon == 1)
  155.         return;
  156.     if (rp->g_token == ICON) {
  157.         rp->g_offs *= kon;
  158.         rp->g_sz = gwiden(rp->g_sz);
  159.         return;
  160.     }
  161.  
  162.     mp = allocnode();
  163.     mp->g_token = '*';
  164.     sprintf(mp->n_name, "p*");
  165.     mp->g_type = E_BIN;
  166.     mp->g_ty = rp->g_ty;
  167.     mp->g_sz = gwiden(rp->g_sz);
  168.  
  169.     kp = newgcon(kon, mp->g_ty, mp->g_sz);
  170.  
  171.     mp->n_right = kp;
  172.     mp->n_left = np->n_right;
  173.     np->n_right = mp;
  174. }
  175.  
  176. ins_div(np, kon)
  177. register NODEP np;
  178. long kon;
  179. {
  180.     register NODEP tp, kp;
  181.  
  182.     kp = newgcon(kon, np->g_ty, np->g_sz);
  183.  
  184.     tp = copyone(np);
  185.     tp->g_token = '-';
  186.     tp->n_left = np->n_left;
  187.     tp->n_right = np->n_right;
  188.     tp->g_sz = SIZE_P;
  189.     tp->g_ty = ET_U;
  190.  
  191.     np->n_left = tp;
  192.     np->n_right = kp;
  193.     np->g_type = E_BIN;
  194.     np->g_token = '/';
  195.     sprintf(np->n_name, "p/");
  196. }
  197.  
  198. #define CAST_LN    1
  199. #define CAST_RN 2
  200. #define CAST_LLONG    3
  201.  
  202. /*
  203.  *    Insert needed (implied) casts
  204.  */
  205. m_cast(np)
  206. NODEP np;
  207. {
  208.     NODEP lp = np->n_left;
  209.  
  210.     switch (np->g_type) {
  211.     case E_LEAF:
  212.         return 0;
  213.     case E_BIN:
  214.         return bm_cast(np);
  215.     }
  216.     /* must be unary */
  217.     switch (np->g_token) {
  218.     case UNARY '-':
  219.     case '~':
  220.         return castup(lp, np, CAST_LN);
  221.     case TCONV:
  222.         return fcastlong(np);
  223.     }
  224.     return 0;
  225. }
  226.  
  227. bm_cast(np)
  228. register NODEP np;
  229. {
  230.     NODEP lp = np->n_left, rp = np->n_right;
  231.  
  232.     if (isassign(np->g_token)) {
  233.         if (castup(rp, lp, CAST_RN))
  234.             return 1;
  235.         if (castmagic(rp, lp, CAST_RN, np->g_token - (ASSIGN 0)))
  236.             return 1;
  237.         return 0;
  238.     }
  239.  
  240.     switch (np->g_token) {
  241.     case '=':
  242.         if (np->g_ty == ET_A)
  243.             return 0;
  244.         return castany(rp, lp, CAST_RN);
  245.  
  246.     case '<':
  247.     case '>':
  248.     case DOUBLE '=':
  249.     case NOTEQ:
  250.     case LTEQ:
  251.     case GTEQ:
  252.         if (castup(lp, rp, CAST_LN))
  253.             return 1;
  254.         return castup(rp, lp, CAST_RN);
  255.  
  256.     case '(':
  257.     case ',':
  258.     case '?':
  259.     case DOUBLE '&':
  260.     case DOUBLE '|':
  261.         return 0;
  262.  
  263.     case DOUBLE '<':
  264.     case DOUBLE '>':
  265.         if (castup(lp, np, CAST_LN))
  266.             return 1;
  267.         return castany(rp, np, CAST_RN);
  268.  
  269.     default:
  270.         if (castup(lp, np, CAST_LN))
  271.             return 1;
  272.         return castup(rp, np, CAST_RN);
  273.     }
  274.     return 0;
  275. }
  276.  
  277. fcastlong(np)
  278. NODEP np;
  279. {
  280.     NODEP lp = np->n_left;
  281.  
  282.     if (red_con(lp))
  283.         return 0;
  284.     if (np->g_ty == ET_F && lp->g_ty != ET_F && lp->g_sz != SIZE_L) {
  285.         ipar1 = CAST_LLONG;
  286.         return 1;
  287.     }
  288.     if (lp->g_ty == ET_F && np->g_ty != ET_F && np->g_sz != SIZE_L) {
  289.         ipar1 = CAST_LLONG;
  290.         return 1;
  291.     }
  292.     return 0;
  293. }
  294.  
  295. castup(lowp, hip, par)
  296. NODEP lowp, hip;
  297. {
  298.     if (stronger(hip, lowp)) {
  299.         ipar1 = par;
  300.         npar1 = hip;
  301.         return 1;
  302.     }
  303.     return 0;
  304. }
  305.  
  306. castmagic(p1, p2, par, tok)
  307. NODEP p1, p2;
  308. {
  309.     if (xstronger(p1,p2) && magicop(tok)) {
  310.         ipar1 = par;
  311.         npar1 = p2;
  312.         return 1;
  313.     }
  314.     return 0;
  315. }
  316.  
  317. castany(p1, p2, par)
  318. NODEP p1, p2;
  319. {
  320.     if (p1->g_sz != p2->g_sz ||
  321.         ((p1->g_ty == ET_F) != (p2->g_ty == ET_F))) {
  322.         ipar1 = par;
  323.         npar1 = p2;
  324.         return 1;
  325.     }
  326.     return 0;
  327. }
  328.  
  329. cast(np)
  330. NODEP np;
  331. {
  332.     switch (ipar1) {
  333.     case CAST_LN:
  334.         castsub(npar1->g_ty, npar1->g_sz, &np->n_left, np->n_left);
  335.         break;
  336.     case CAST_RN:
  337.         castsub(npar1->g_ty, npar1->g_sz, &np->n_right, np->n_right);
  338.         break;
  339.     case CAST_LLONG:
  340.         castsub(ET_S, SIZE_L, &np->n_left, np->n_left);
  341.         break;
  342.     }
  343. }
  344.  
  345. castsub(ty, sz, npp, np)
  346. NODEP *npp, np;
  347. {
  348.     register NODEP tp;
  349.  
  350.     /* ICON cast optimization */
  351.     if (np->g_token == ICON &&
  352.         np->g_ty == ty &&
  353.         np->g_sz < sz) {
  354.         np->g_sz = sz;
  355.         return;
  356.     }
  357.  
  358.     tp = allocnode();
  359.     tp->g_token = TCONV;
  360.     strcpy(tp->n_name, "cast up");
  361.     tp->n_left = np;
  362.     *npp = tp;
  363.     tp->g_sz = sz;
  364.     tp->g_ty = ty;
  365.     tp->g_type = E_UNARY;
  366. }
  367.  
  368. /*
  369.  *    Change stuff computer cant do to calls to inline functions
  370.  *    (in this case, all floats and long *%/)
  371.  */
  372. m_inline(np)
  373. NODEP np;
  374. {
  375.     int isfloat, isuns;
  376.  
  377.     if (np->g_type == E_LEAF)
  378.         return 0;
  379.  
  380.     if (np->g_ty == ET_A)
  381.         return 0;
  382.     isfloat = (np->g_ty == ET_F);
  383.     isuns = (np->g_ty == ET_U);
  384.  
  385.     if (np->g_type == E_UNARY) {
  386.         switch (np->g_token) {
  387.         case UNARY '-':
  388.             if (!isfloat) return 0;
  389.             spar1 = "%fpneg";
  390.             return 1;
  391.         case TCONV:
  392.             if ((np->n_left->g_ty == ET_F) == isfloat)
  393.                 return 0;
  394.             if (red_con(np->n_left))
  395.                 return 0;
  396.             spar1 = isfloat ? "fpltof" : "fpftol";
  397.             return 1;
  398.         }
  399.         return 0;
  400.     }
  401.  
  402.     if (np->g_sz != 4)    /* longs or floats only */
  403.         return 0;
  404.  
  405.     switch (np->g_token) {
  406.     case '*':
  407.         spar1 = isfloat ? "%fpmul" : (isuns ? "%lmulu" : "%lmul");
  408.         return 1;
  409.     case '/':
  410.         spar1 = isfloat ? "%fpdiv" : (isuns ? "%ldivu" : "%ldiv");
  411.         return 1;
  412.     case '+':
  413.         if (!isfloat) return 0;
  414.         spar1 = "%fpadd";
  415.         return 1;
  416.     case '-':
  417.         if (!isfloat) return 0;
  418.         spar1 = "%fpsub";
  419.         return 1;
  420.     case '%':
  421.         spar1 = isuns ? "%lremu" : "%lrem";
  422.         return 1;
  423.     }
  424.     return 0;
  425. }
  426.  
  427. inline(np)
  428. NODEP np;
  429. {
  430.     register NODEP nmp, cmap;
  431.     int isunary;
  432.  
  433.     isunary = (np->g_type == E_UNARY);
  434.  
  435.     if (isunary) {
  436.         np->n_right = np->n_left;
  437.         np->g_type = E_BIN;
  438.     } else {
  439.         cmap = copyone(np);
  440.         cmap->n_left = np->n_left;
  441.         cmap->n_right = np->n_right;
  442.         np->n_right = cmap;
  443.  
  444.         cmap->g_token = ',';
  445.         cmap->g_offs = 2;
  446.         strcpy(cmap->n_name, ",inl");
  447.     }
  448.  
  449.     nmp = allocnode();
  450.     np->n_left = nmp;
  451.  
  452.     np->g_token = '(';
  453.     strcpy(np->n_name, "inline");
  454.  
  455.     nmp->g_token = ID;
  456.     strcpy(nmp->n_name, spar1);
  457. #ifdef OUT_AZ
  458.     strcat(nmp->n_name, "#");
  459. #endif
  460. }
  461.  
  462. /*
  463.  *    Transform hard ++,-- to equivalent trees
  464.  *    (for us, floats or fields)
  465.  */
  466. m_incdec(np)
  467. NODEP np;
  468. {
  469.     if (np->g_type != E_UNARY)
  470.         return 0;
  471.     if (np->g_ty != ET_F && !isfield(np->n_left))
  472.         return 0;
  473.  
  474.     ipar2 = 0;
  475.     switch (np->g_token) {
  476.     case DOUBLE '+':
  477.         ipar1 = ASSIGN '+';
  478.         spar1 = "+=";
  479.         break;
  480.     case DOUBLE '-':
  481.         ipar1 = ASSIGN '-';
  482.         spar1 = "-=";
  483.         break;
  484.     case POSTINC:
  485.         ipar1 = DOUBLE '+';
  486.         spar1 = "++";
  487.         ipar2 = '-';
  488.         spar2 = "-";
  489.         break;
  490.     case POSTDEC:
  491.         ipar1 = DOUBLE '-';
  492.         spar1 = "--";
  493.         ipar2 = '+';
  494.         spar2 = "+";
  495.         break;
  496.     default:
  497.         return 0;
  498.     }
  499.     return 1;
  500. }
  501.  
  502. incdec(np)
  503. register NODEP np;
  504. {
  505.     NODEP t1;
  506.     NODEP onep;
  507.  
  508.     onep = newgcon(1L, ET_S, SIZE_I);
  509.  
  510.     if (ipar2 == 0) {        /* easy case, ++X becomes X+=1 */
  511.         np->g_token = ipar1;
  512.         np->g_type = E_BIN;
  513.         np->n_right = onep;
  514.         strcpy(np->n_name, spar1);
  515.         return;
  516.     }
  517.  
  518.     /* hard case, X++ becomes (++X - 1) */
  519.     t1 = copyone(np);
  520.     t1->n_left = np->n_left;
  521.     np->n_left = t1;
  522.     np->n_right = onep;
  523.     np->g_type = E_BIN;
  524.     np->g_token = ipar2;
  525.     strcpy(np->n_name, spar2);
  526.  
  527.     t1->g_token = ipar1;
  528.     strcpy(t1->n_name, spar1);
  529. }
  530.  
  531. /*
  532.  *    Transform hard op= trees to equivalent '=' trees
  533.  *    (in this case, all floats, long or char *%/, fields)
  534.  */
  535. m_hardas(np)
  536. NODEP np;
  537. {
  538.     int op;
  539.  
  540.     if (np->g_type != E_BIN)
  541.         return 0;
  542.     op = np->g_token;
  543.     if (isassign(op))
  544.         op -= ASSIGN 0;
  545.     else
  546.         return 0;
  547.     if (xstronger(np->n_right, np->n_left) &&
  548.         magicop(op) == 0)
  549.         return 1;
  550.     if (np->g_ty == ET_F || isfield(np->n_left))
  551.         return 1;
  552.     if (np->g_sz == 4 || np->g_sz == 1)
  553.         switch (op) {
  554.         case '*':
  555.         case '/':
  556.         case '%':
  557.             return 1;
  558.         }
  559.     return 0;
  560. }
  561.  
  562. hardas(np)
  563. NODEP np;
  564. {
  565.     NODEP opp, newl;
  566.     NODEP copynode();
  567.  
  568.     if (m_vhard(np)) {
  569.         vhard(np);
  570.         return;
  571.     }
  572.  
  573.     opp = copyone(np);
  574.     newl = copynode(np->n_left);
  575.     opp->n_right = np->n_right;
  576.     np->n_right = opp;
  577.     opp->n_left = newl;
  578.  
  579.     np->g_token = '=';
  580.     strcpy(np->n_name, "unfold");
  581.  
  582.     opp->g_token -= (ASSIGN 0);
  583.     bmaxty(opp);
  584. }
  585.  
  586. /*
  587.  *    Check for lhs of op= that have side effects or are complex
  588.  */
  589. m_vhard(np)
  590. NODEP np;
  591. {
  592.     NODEP lp = np->n_left;
  593.  
  594.     while (lp->g_token == '.')
  595.         lp = lp->n_left;
  596.     if (lp->g_token != STAR)
  597.         return 0;
  598.     return isvhard(lp->n_left);
  599. }
  600.  
  601. isvhard(np)
  602. NODEP np;
  603. {
  604.     NODEP rp;
  605.  
  606. descend:
  607.     switch (np->g_type) {
  608.     case E_LEAF:
  609.         return 0;
  610.     case E_UNARY:
  611.         switch (np->g_token) {
  612.         case '(':
  613.         case DOUBLE '+':
  614.         case DOUBLE '-':
  615.         case POSTINC:
  616.         case POSTDEC:
  617.             return 1;
  618.         default:
  619.             np = np->n_left;
  620.             goto descend;
  621.         }
  622.     case E_BIN:
  623.         switch (np->g_token) {
  624.         case '+':
  625.         case '-':
  626.             rp = np->n_right;
  627.             if (rp->g_token == ICON && np->g_ty != ET_F) {
  628.                 np = np->n_left;
  629.                 goto descend;
  630.             }
  631.             /* fall through */
  632.         default:
  633.             return 1;
  634.         }
  635.     }
  636. }
  637.  
  638. vhard(np)
  639. NODEP np;
  640. {
  641.     NODEP starp;
  642.     NODEP atree, btree;
  643.     NODEP t1, t2;
  644.     register NODEP opp;
  645.     NODEP tmp_var();
  646.  
  647.     starp = np->n_left;
  648.     while (starp->g_token == '.')
  649.         starp = starp->n_left;
  650.     atree = starp->n_left;
  651.     btree = np->n_right;
  652.     t1 = tmp_var(ET_U, SIZE_P);
  653.     t2 = copyone(t1);
  654.     starp->n_left = t2;
  655.  
  656.     opp = copyone(t1);
  657.     opp->g_type = E_BIN;
  658.     opp->g_token = '=';
  659.     strcpy(opp->n_name, "=");
  660.     opp->n_right = atree;
  661.     opp->n_left = t1;
  662.  
  663.     comma_r(np, opp);
  664. }
  665.  
  666. comma_r(topp, lp)
  667. NODEP topp, lp;
  668. {
  669.     register NODEP newp;
  670.  
  671.     newp = copyone(topp);
  672.     topp->g_token = ',';
  673.     strcpy(topp->n_name, ",");
  674.     newp->n_left = topp->n_left;
  675.     newp->n_right = topp->n_right;
  676.     topp->n_left = lp;
  677.     topp->n_right = newp;
  678. }
  679.  
  680. NODEP
  681. tmp_var(ty, sz)
  682. {
  683.     register NODEP t1;
  684.  
  685.     t1 = allocnode();
  686.     t1->g_token = OREG;
  687.     t1->g_type = E_LEAF;
  688.     t1->g_rno = AREG+6;
  689.     t1->g_ty = ty;
  690.     t1->g_sz = sz;
  691.     t1->g_offs = - tmp_alloc(sz);
  692.     strcpy(t1->n_name, "tmp_v");
  693.     return t1;
  694. }
  695.  
  696. /* X op= Y where Y's type is stronger than X's
  697.     either unfold it or (default)
  698.     cast Y to weaker type (+ or -)
  699. */
  700.  
  701. magicop(op)
  702. {
  703.     switch (op) {
  704.     case '+':
  705.     case '-':
  706.     case DOUBLE '<':
  707.     case DOUBLE '>':
  708.     case '&':
  709.     case '|':
  710.     case '^':
  711.         return 1;
  712.     }
  713.     return 0;
  714. }
  715.  
  716. stronger(xp, yp)
  717. NODEP xp, yp;
  718. {
  719.     if (xp->g_sz > yp->g_sz || 
  720.         (xp->g_sz == yp->g_sz && xp->g_ty > yp->g_ty))
  721.         return 1;
  722.     return 0;
  723. }
  724.  
  725. /* stronger with ET_S and ET_U considered equal */
  726. xstronger(xp, yp)
  727. NODEP xp, yp;
  728. {
  729.     if (xp->g_sz > yp->g_sz ||
  730.         (xp->g_ty == ET_F && yp->g_ty != ET_F))
  731.         return 1;
  732.     return 0;
  733. }
  734.  
  735. /* give np the type of the stronger child */
  736. bmaxty(np)
  737. NODEP np;
  738. {
  739.     NODEP lp = np->n_left, rp = np->n_right;
  740.  
  741.     if (stronger(lp, rp))
  742.         rp = lp;
  743.     np->g_ty = rp->g_ty;
  744.     np->g_sz = gwiden(rp->g_sz);
  745. }
  746.  
  747. /*
  748.  *    Change floating compares to inline call 
  749.  */
  750. m_fcmp(np)
  751. NODEP np;
  752. {
  753.         /* already made L and R same with casts */
  754.     if (np->g_type != E_BIN || np->n_left->g_ty != ET_F)
  755.         return 0;
  756.     switch (np->g_token) {
  757.     case '<':
  758.         spar2 = "lt";
  759.         return 1;
  760.     case '>':
  761.         spar2 = "gt";
  762.         return 1;
  763.     case DOUBLE '=':
  764.         spar2 = "eq";
  765.         return 1;
  766.     case NOTEQ:
  767.         spar2 = "ne";
  768.         return 1;
  769.     case GTEQ:
  770.         spar2 = "ge";
  771.         return 1;
  772.     case LTEQ:
  773.         spar2 = "le";
  774.         return 1;
  775.     }
  776.     return 0;
  777. }
  778.  
  779. fcmp(np)
  780. register NODEP np;
  781. {
  782.     register NODEP tp;
  783.  
  784.     spar1 = "%fpcmp";
  785.     inline(np);
  786.  
  787.     tp = copyone(np);
  788.     tp->n_left = np->n_left;
  789.     tp->n_right = np->n_right;
  790.     np->n_left = tp;
  791.  
  792.     np->n_right = NULL;
  793.     np->g_type = E_UNARY;
  794.     np->g_token = CMPBR;
  795.     sprintf(np->n_name, spar2);
  796. }
  797.  
  798. /*
  799.  *    Remove useless binary operations with identity constant
  800.  */
  801. m_eident(np)
  802. NODEP np;
  803. {
  804.     NODEP rp = np->n_right;
  805.     long l;
  806.     int i, op;
  807.  
  808.     if (np->g_type != E_BIN)
  809.         return 0;
  810.     if (np->g_ty == ET_F)
  811.         return 0;
  812.     while (rp->g_token == TCONV && rp->g_ty != ET_F)
  813.         rp = rp->n_left;
  814.     if (rp->g_token != ICON)
  815.         return 0;
  816.     l = rp->g_offs;
  817.     if (l < 0 || l > 1)
  818.         return 0;
  819.  
  820.     op = np->g_token;
  821.     if (isassign(op))
  822.         op -= ASSIGN 0;
  823.     switch (op) {
  824.     case '+':
  825.     case '-':
  826.     case DOUBLE '<':
  827.     case DOUBLE '>':
  828.     case '|':
  829.     case '^':
  830.         i = 0;    break;
  831.     case '*':
  832.     case '/':
  833.         i = 1;  break;
  834.     default:
  835.         return 0;
  836.     }
  837.     if (l != i)
  838.         return 0;
  839.     return 1;    
  840. }
  841.  
  842. eident(np)
  843. NODEP np;
  844. {
  845.     NODEP lp = np->n_left, rp = np->n_right;
  846.  
  847.     freenode(rp);
  848.     
  849.     lcpy(np, lp, sizeof(NODE)/4);
  850.  
  851.     freeunit(lp);
  852. }
  853.  
  854. #define MAXLOOK    8
  855.  
  856. /*
  857.  *    Change certain mult or div to equivalent shift
  858.  */
  859. m_md_shf(np)
  860. NODEP np;
  861. {
  862.     NODEP rp = np->n_right;
  863.     long l;
  864.     register i, j;
  865.  
  866.     if (np->g_type != E_BIN)
  867.         return 0;
  868.     if (np->g_ty == ET_F)
  869.         return 0;
  870.     while (rp->g_token == TCONV && rp->g_ty != ET_F)
  871.         rp = rp->n_left;
  872.     if (rp->g_token != ICON)
  873.         return 0;
  874.  
  875.     switch (np->g_token) {
  876.     case '*':
  877.         ipar1 = DOUBLE '<';  break;
  878.     case '/':
  879.         ipar1 = DOUBLE '>';  break;
  880.     case ASSIGN '*':
  881.         ipar1 = ASSIGN DOUBLE '<';  break;
  882.     case ASSIGN '/':
  883.         ipar1 = ASSIGN DOUBLE '>';  break;
  884.     default:
  885.         return 0;
  886.     }
  887.  
  888.     l = rp->g_offs;
  889.     if (l < 2 || l > (1<<MAXLOOK))
  890.         return 0;
  891.     i = l;
  892.     for (j=1; j<=MAXLOOK; j++)
  893.         if (i == 1<<j) {
  894.             ipar2 = j;
  895.             return 1;
  896.         }
  897.     return 0;
  898. }
  899.  
  900. md_shf(np)
  901. NODEP np;
  902. {
  903.     NODEP rp = np->n_right;
  904.  
  905.     np->g_token = ipar1;
  906.     while (rp->g_token == TCONV)
  907.         rp = rp->n_left;
  908.     rp->g_offs = ipar2;
  909. }
  910.  
  911. m_fldas(np)
  912. NODEP np;
  913. {
  914.     if (np->g_type != E_BIN)
  915.         return 0;
  916.     if (np->g_token == '=' && isfield(np->n_left))
  917.         return 1;
  918.     return 0;
  919. }
  920.  
  921. fldas(np)
  922. register NODEP np;
  923. {
  924.     NODEP lp = np->n_left;
  925.  
  926.     np->g_fldw = lp->g_fldw;
  927.     np->g_fldo = lp->g_fldo;
  928.     np->g_token = FIELDAS;
  929.  
  930.     lp->g_fldw = 0;
  931. }
  932.  
  933. red_con(np)
  934. register NODEP np;
  935. {
  936.     while (np->g_token == TCONV)
  937.         np = np->n_left;
  938.     if (np->g_token == ICON || np->g_token == FCON)
  939.         return 1;
  940.     return 0;
  941. }
  942.