home *** CD-ROM | disk | FTP | other *** search
- /* Copyright (c) 1988 by Sozobon, Limited. Author: Johann Ruegg
- *
- * Permission is granted to anyone to use this software for any purpose
- * on any computer system, and to redistribute it freely, with the
- * following restrictions:
- * 1) No charge may be made other than reasonable charges for reproduction.
- * 2) Modified versions must be clearly marked as such.
- * 3) The authors are not responsible for any harmful consequences
- * of using this software, even if they result from defects in it.
- *
- * gunk.c
- *
- * Transformations on expression trees
- * Most of this stuff is because we cant handle
- * floats, long mul/div, or fields directly.
- */
-
- #include <stdio.h>
- #include "param.h"
- #include "bstok.h"
- #include "tytok.h"
- #include "flags.h"
- #include "nodes.h"
- #include "gen.h"
-
- NODEP copyone();
-
- #define gwiden(x) ((x)==1 ? 2 : (x))
- #define isfield(np) ((np)->g_token == '.' && (np)->g_fldw)
-
- NODEP npar1, npar2, npar3;
- char *spar1, *spar2, *spar3;
- int ipar1, ipar2, ipar3;
-
- struct rule {
- int (*match)(); /* test for transformation needed */
- int (*rewri)(); /* rewrite function */
- };
-
- int m_unfold(), unfold(), m_cast(), cast(), m_inline(), inline();
- int m_hardas(), hardas(), m_fcmp(), fcmp(), m_md_shf(), md_shf();
- int m_eident(), eident(), m_incdec(), incdec(), m_fldas(), fldas();
-
- struct rule gunktbl[] = {
- {m_unfold, unfold},
- {m_cast, cast},
- {m_md_shf, md_shf},
- {m_eident, eident},
- {m_incdec, incdec},
- {m_hardas, hardas},
- {m_inline, inline}, /* must cast before inline */
- {m_fcmp, fcmp},
- {m_fldas, fldas},
- {0}
- };
-
- int anygunk;
-
- gunk(np)
- NODEP np;
- {
- do {
- anygunk = 0;
- gunks(np);
- } while (anygunk);
- }
-
- gunks(np)
- register NODEP np;
- {
- switch (np->g_type) {
- case E_BIN:
- gunks(np->n_right);
- case E_UNARY:
- gunks(np->n_left);
- }
- gunk1(np);
- }
-
- gunk1(np)
- NODEP np;
- {
- register struct rule *p;
-
- for (p=gunktbl; p->match; p++)
- if ((*p->match)(np)) {
- anygunk++;
- (*p->rewri)(np);
- return;
- }
- }
-
- /*
- * Change pointer arithmetic to equivalent trees
- * (main thing is to mult or div by object size)
- */
- m_unfold(np)
- NODEP np;
- {
- switch (np->g_token) {
- case PTRADD:
- ipar1 = '+';
- return 1;
- case PTRSUB:
- ipar1 = '-';
- return 1;
- case PTRDIFF:
- ipar1 = 0;
- return 1;
- case ASSIGN PTRADD:
- ipar1 = ASSIGN '+';
- return 1;
- case ASSIGN PTRSUB:
- ipar1 = ASSIGN '-';
- return 1;
- }
- return 0;
- }
-
- unfold(np)
- NODEP np;
- {
- if (ipar1) {
- ins_mul(np, np->g_offs);
- np->g_token = ipar1;
- } else {
- ins_div(np, np->g_offs);
- }
- }
-
- NODEP
- newgcon(kon, ty, sz)
- long kon;
- {
- register NODEP kp;
-
- kp = allocnode();
- kp->g_token = ICON;
- sprintf(kp->n_name, "%ld", kon);
- kp->g_offs = kon;
- kp->g_type = E_LEAF;
- kp->g_ty = ty;
- kp->g_sz = sz;
- return kp;
- }
-
- ins_mul(np, kon)
- NODEP np;
- long kon;
- {
- NODEP rp = np->n_right;
- register NODEP mp, kp;
-
- if (kon == 1)
- return;
- if (rp->g_token == ICON) {
- rp->g_offs *= kon;
- rp->g_sz = gwiden(rp->g_sz);
- return;
- }
-
- mp = allocnode();
- mp->g_token = '*';
- sprintf(mp->n_name, "p*");
- mp->g_type = E_BIN;
- mp->g_ty = rp->g_ty;
- mp->g_sz = gwiden(rp->g_sz);
-
- kp = newgcon(kon, mp->g_ty, mp->g_sz);
-
- mp->n_right = kp;
- mp->n_left = np->n_right;
- np->n_right = mp;
- }
-
- ins_div(np, kon)
- register NODEP np;
- long kon;
- {
- register NODEP tp, kp;
-
- kp = newgcon(kon, np->g_ty, np->g_sz);
-
- tp = copyone(np);
- tp->g_token = '-';
- tp->n_left = np->n_left;
- tp->n_right = np->n_right;
- tp->g_sz = SIZE_P;
- tp->g_ty = ET_U;
-
- np->n_left = tp;
- np->n_right = kp;
- np->g_type = E_BIN;
- np->g_token = '/';
- sprintf(np->n_name, "p/");
- }
-
- #define CAST_LN 1
- #define CAST_RN 2
- #define CAST_LLONG 3
-
- /*
- * Insert needed (implied) casts
- */
- m_cast(np)
- NODEP np;
- {
- NODEP lp = np->n_left;
-
- switch (np->g_type) {
- case E_LEAF:
- return 0;
- case E_BIN:
- return bm_cast(np);
- }
- /* must be unary */
- switch (np->g_token) {
- case UNARY '-':
- case '~':
- return castup(lp, np, CAST_LN);
- case TCONV:
- return fcastlong(np);
- }
- return 0;
- }
-
- bm_cast(np)
- register NODEP np;
- {
- NODEP lp = np->n_left, rp = np->n_right;
-
- if (isassign(np->g_token)) {
- if (castup(rp, lp, CAST_RN))
- return 1;
- if (castmagic(rp, lp, CAST_RN, np->g_token - (ASSIGN 0)))
- return 1;
- return 0;
- }
-
- switch (np->g_token) {
- case '=':
- if (np->g_ty == ET_A)
- return 0;
- return castany(rp, lp, CAST_RN);
-
- case '<':
- case '>':
- case DOUBLE '=':
- case NOTEQ:
- case LTEQ:
- case GTEQ:
- if (castup(lp, rp, CAST_LN))
- return 1;
- return castup(rp, lp, CAST_RN);
-
- case '(':
- case ',':
- case '?':
- case DOUBLE '&':
- case DOUBLE '|':
- return 0;
-
- case DOUBLE '<':
- case DOUBLE '>':
- if (castup(lp, np, CAST_LN))
- return 1;
- return castany(rp, np, CAST_RN);
-
- default:
- if (castup(lp, np, CAST_LN))
- return 1;
- return castup(rp, np, CAST_RN);
- }
- return 0;
- }
-
- fcastlong(np)
- NODEP np;
- {
- NODEP lp = np->n_left;
-
- if (red_con(lp))
- return 0;
- if (np->g_ty == ET_F && lp->g_ty != ET_F && lp->g_sz != SIZE_L) {
- ipar1 = CAST_LLONG;
- return 1;
- }
- if (lp->g_ty == ET_F && np->g_ty != ET_F && np->g_sz != SIZE_L) {
- ipar1 = CAST_LLONG;
- return 1;
- }
- return 0;
- }
-
- castup(lowp, hip, par)
- NODEP lowp, hip;
- {
- if (stronger(hip, lowp)) {
- ipar1 = par;
- npar1 = hip;
- return 1;
- }
- return 0;
- }
-
- castmagic(p1, p2, par, tok)
- NODEP p1, p2;
- {
- if (xstronger(p1,p2) && magicop(tok)) {
- ipar1 = par;
- npar1 = p2;
- return 1;
- }
- return 0;
- }
-
- castany(p1, p2, par)
- NODEP p1, p2;
- {
- if (p1->g_sz != p2->g_sz ||
- ((p1->g_ty == ET_F) != (p2->g_ty == ET_F))) {
- ipar1 = par;
- npar1 = p2;
- return 1;
- }
- return 0;
- }
-
- cast(np)
- NODEP np;
- {
- switch (ipar1) {
- case CAST_LN:
- castsub(npar1->g_ty, npar1->g_sz, &np->n_left, np->n_left);
- break;
- case CAST_RN:
- castsub(npar1->g_ty, npar1->g_sz, &np->n_right, np->n_right);
- break;
- case CAST_LLONG:
- castsub(ET_S, SIZE_L, &np->n_left, np->n_left);
- break;
- }
- }
-
- castsub(ty, sz, npp, np)
- NODEP *npp, np;
- {
- register NODEP tp;
-
- /* ICON cast optimization */
- if (np->g_token == ICON &&
- np->g_ty == ty &&
- np->g_sz < sz) {
- np->g_sz = sz;
- return;
- }
-
- tp = allocnode();
- tp->g_token = TCONV;
- strcpy(tp->n_name, "cast up");
- tp->n_left = np;
- *npp = tp;
- tp->g_sz = sz;
- tp->g_ty = ty;
- tp->g_type = E_UNARY;
- }
-
- /*
- * Change stuff computer cant do to calls to inline functions
- * (in this case, all floats and long *%/)
- */
- m_inline(np)
- NODEP np;
- {
- int isfloat, isuns;
-
- if (np->g_type == E_LEAF)
- return 0;
-
- if (np->g_ty == ET_A)
- return 0;
- isfloat = (np->g_ty == ET_F);
- isuns = (np->g_ty == ET_U);
-
- if (np->g_type == E_UNARY) {
- switch (np->g_token) {
- case UNARY '-':
- if (!isfloat) return 0;
- spar1 = "%fpneg";
- return 1;
- case TCONV:
- if ((np->n_left->g_ty == ET_F) == isfloat)
- return 0;
- if (red_con(np->n_left))
- return 0;
- spar1 = isfloat ? "fpltof" : "fpftol";
- return 1;
- }
- return 0;
- }
-
- if (np->g_sz != 4) /* longs or floats only */
- return 0;
-
- switch (np->g_token) {
- case '*':
- spar1 = isfloat ? "%fpmul" : (isuns ? "%lmulu" : "%lmul");
- return 1;
- case '/':
- spar1 = isfloat ? "%fpdiv" : (isuns ? "%ldivu" : "%ldiv");
- return 1;
- case '+':
- if (!isfloat) return 0;
- spar1 = "%fpadd";
- return 1;
- case '-':
- if (!isfloat) return 0;
- spar1 = "%fpsub";
- return 1;
- case '%':
- spar1 = isuns ? "%lremu" : "%lrem";
- return 1;
- }
- return 0;
- }
-
- inline(np)
- NODEP np;
- {
- register NODEP nmp, cmap;
- int isunary;
-
- isunary = (np->g_type == E_UNARY);
-
- if (isunary) {
- np->n_right = np->n_left;
- np->g_type = E_BIN;
- } else {
- cmap = copyone(np);
- cmap->n_left = np->n_left;
- cmap->n_right = np->n_right;
- np->n_right = cmap;
-
- cmap->g_token = ',';
- cmap->g_offs = 2;
- strcpy(cmap->n_name, ",inl");
- }
-
- nmp = allocnode();
- np->n_left = nmp;
-
- np->g_token = '(';
- strcpy(np->n_name, "inline");
-
- nmp->g_token = ID;
- strcpy(nmp->n_name, spar1);
- #ifdef OUT_AZ
- strcat(nmp->n_name, "#");
- #endif
- }
-
- /*
- * Transform hard ++,-- to equivalent trees
- * (for us, floats or fields)
- */
- m_incdec(np)
- NODEP np;
- {
- if (np->g_type != E_UNARY)
- return 0;
- if (np->g_ty != ET_F && !isfield(np->n_left))
- return 0;
-
- ipar2 = 0;
- switch (np->g_token) {
- case DOUBLE '+':
- ipar1 = ASSIGN '+';
- spar1 = "+=";
- break;
- case DOUBLE '-':
- ipar1 = ASSIGN '-';
- spar1 = "-=";
- break;
- case POSTINC:
- ipar1 = DOUBLE '+';
- spar1 = "++";
- ipar2 = '-';
- spar2 = "-";
- break;
- case POSTDEC:
- ipar1 = DOUBLE '-';
- spar1 = "--";
- ipar2 = '+';
- spar2 = "+";
- break;
- default:
- return 0;
- }
- return 1;
- }
-
- incdec(np)
- register NODEP np;
- {
- NODEP t1;
- NODEP onep;
-
- onep = newgcon(1L, ET_S, SIZE_I);
-
- if (ipar2 == 0) { /* easy case, ++X becomes X+=1 */
- np->g_token = ipar1;
- np->g_type = E_BIN;
- np->n_right = onep;
- strcpy(np->n_name, spar1);
- return;
- }
-
- /* hard case, X++ becomes (++X - 1) */
- t1 = copyone(np);
- t1->n_left = np->n_left;
- np->n_left = t1;
- np->n_right = onep;
- np->g_type = E_BIN;
- np->g_token = ipar2;
- strcpy(np->n_name, spar2);
-
- t1->g_token = ipar1;
- strcpy(t1->n_name, spar1);
- }
-
- /*
- * Transform hard op= trees to equivalent '=' trees
- * (in this case, all floats, long or char *%/, fields)
- */
- m_hardas(np)
- NODEP np;
- {
- int op;
-
- if (np->g_type != E_BIN)
- return 0;
- op = np->g_token;
- if (isassign(op))
- op -= ASSIGN 0;
- else
- return 0;
- if (xstronger(np->n_right, np->n_left) &&
- magicop(op) == 0)
- return 1;
- if (np->g_ty == ET_F || isfield(np->n_left))
- return 1;
- if (np->g_sz == 4 || np->g_sz == 1)
- switch (op) {
- case '*':
- case '/':
- case '%':
- return 1;
- }
- return 0;
- }
-
- hardas(np)
- NODEP np;
- {
- NODEP opp, newl;
- NODEP copynode();
-
- if (m_vhard(np)) {
- vhard(np);
- return;
- }
-
- opp = copyone(np);
- newl = copynode(np->n_left);
- opp->n_right = np->n_right;
- np->n_right = opp;
- opp->n_left = newl;
-
- np->g_token = '=';
- strcpy(np->n_name, "unfold");
-
- opp->g_token -= (ASSIGN 0);
- bmaxty(opp);
- }
-
- /*
- * Check for lhs of op= that have side effects or are complex
- */
- m_vhard(np)
- NODEP np;
- {
- NODEP lp = np->n_left;
-
- while (lp->g_token == '.')
- lp = lp->n_left;
- if (lp->g_token != STAR)
- return 0;
- return isvhard(lp->n_left);
- }
-
- isvhard(np)
- NODEP np;
- {
- NODEP rp;
-
- descend:
- switch (np->g_type) {
- case E_LEAF:
- return 0;
- case E_UNARY:
- switch (np->g_token) {
- case '(':
- case DOUBLE '+':
- case DOUBLE '-':
- case POSTINC:
- case POSTDEC:
- return 1;
- default:
- np = np->n_left;
- goto descend;
- }
- case E_BIN:
- switch (np->g_token) {
- case '+':
- case '-':
- rp = np->n_right;
- if (rp->g_token == ICON && np->g_ty != ET_F) {
- np = np->n_left;
- goto descend;
- }
- /* fall through */
- default:
- return 1;
- }
- }
- }
-
- vhard(np)
- NODEP np;
- {
- NODEP starp;
- NODEP atree, btree;
- NODEP t1, t2;
- register NODEP opp;
- NODEP tmp_var();
-
- starp = np->n_left;
- while (starp->g_token == '.')
- starp = starp->n_left;
- atree = starp->n_left;
- btree = np->n_right;
- t1 = tmp_var(ET_U, SIZE_P);
- t2 = copyone(t1);
- starp->n_left = t2;
-
- opp = copyone(t1);
- opp->g_type = E_BIN;
- opp->g_token = '=';
- strcpy(opp->n_name, "=");
- opp->n_right = atree;
- opp->n_left = t1;
-
- comma_r(np, opp);
- }
-
- comma_r(topp, lp)
- NODEP topp, lp;
- {
- register NODEP newp;
-
- newp = copyone(topp);
- topp->g_token = ',';
- strcpy(topp->n_name, ",");
- newp->n_left = topp->n_left;
- newp->n_right = topp->n_right;
- topp->n_left = lp;
- topp->n_right = newp;
- }
-
- NODEP
- tmp_var(ty, sz)
- {
- register NODEP t1;
-
- t1 = allocnode();
- t1->g_token = OREG;
- t1->g_type = E_LEAF;
- t1->g_rno = AREG+6;
- t1->g_ty = ty;
- t1->g_sz = sz;
- t1->g_offs = - tmp_alloc(sz);
- strcpy(t1->n_name, "tmp_v");
- return t1;
- }
-
- /* X op= Y where Y's type is stronger than X's
- either unfold it or (default)
- cast Y to weaker type (+ or -)
- */
-
- magicop(op)
- {
- switch (op) {
- case '+':
- case '-':
- case DOUBLE '<':
- case DOUBLE '>':
- case '&':
- case '|':
- case '^':
- return 1;
- }
- return 0;
- }
-
- stronger(xp, yp)
- NODEP xp, yp;
- {
- if (xp->g_sz > yp->g_sz ||
- (xp->g_sz == yp->g_sz && xp->g_ty > yp->g_ty))
- return 1;
- return 0;
- }
-
- /* stronger with ET_S and ET_U considered equal */
- xstronger(xp, yp)
- NODEP xp, yp;
- {
- if (xp->g_sz > yp->g_sz ||
- (xp->g_ty == ET_F && yp->g_ty != ET_F))
- return 1;
- return 0;
- }
-
- /* give np the type of the stronger child */
- bmaxty(np)
- NODEP np;
- {
- NODEP lp = np->n_left, rp = np->n_right;
-
- if (stronger(lp, rp))
- rp = lp;
- np->g_ty = rp->g_ty;
- np->g_sz = gwiden(rp->g_sz);
- }
-
- /*
- * Change floating compares to inline call
- */
- m_fcmp(np)
- NODEP np;
- {
- /* already made L and R same with casts */
- if (np->g_type != E_BIN || np->n_left->g_ty != ET_F)
- return 0;
- switch (np->g_token) {
- case '<':
- spar2 = "lt";
- return 1;
- case '>':
- spar2 = "gt";
- return 1;
- case DOUBLE '=':
- spar2 = "eq";
- return 1;
- case NOTEQ:
- spar2 = "ne";
- return 1;
- case GTEQ:
- spar2 = "ge";
- return 1;
- case LTEQ:
- spar2 = "le";
- return 1;
- }
- return 0;
- }
-
- fcmp(np)
- register NODEP np;
- {
- register NODEP tp;
-
- spar1 = "%fpcmp";
- inline(np);
-
- tp = copyone(np);
- tp->n_left = np->n_left;
- tp->n_right = np->n_right;
- np->n_left = tp;
-
- np->n_right = NULL;
- np->g_type = E_UNARY;
- np->g_token = CMPBR;
- sprintf(np->n_name, spar2);
- }
-
- /*
- * Remove useless binary operations with identity constant
- */
- m_eident(np)
- NODEP np;
- {
- NODEP rp = np->n_right;
- long l;
- int i, op;
-
- if (np->g_type != E_BIN)
- return 0;
- if (np->g_ty == ET_F)
- return 0;
- while (rp->g_token == TCONV && rp->g_ty != ET_F)
- rp = rp->n_left;
- if (rp->g_token != ICON)
- return 0;
- l = rp->g_offs;
- if (l < 0 || l > 1)
- return 0;
-
- op = np->g_token;
- if (isassign(op))
- op -= ASSIGN 0;
- switch (op) {
- case '+':
- case '-':
- case DOUBLE '<':
- case DOUBLE '>':
- case '|':
- case '^':
- i = 0; break;
- case '*':
- case '/':
- i = 1; break;
- default:
- return 0;
- }
- if (l != i)
- return 0;
- return 1;
- }
-
- eident(np)
- NODEP np;
- {
- NODEP lp = np->n_left, rp = np->n_right;
-
- freenode(rp);
-
- lcpy(np, lp, sizeof(NODE)/4);
-
- freeunit(lp);
- }
-
- #define MAXLOOK 8
-
- /*
- * Change certain mult or div to equivalent shift
- */
- m_md_shf(np)
- NODEP np;
- {
- NODEP rp = np->n_right;
- long l;
- register i, j;
-
- if (np->g_type != E_BIN)
- return 0;
- if (np->g_ty == ET_F)
- return 0;
- while (rp->g_token == TCONV && rp->g_ty != ET_F)
- rp = rp->n_left;
- if (rp->g_token != ICON)
- return 0;
-
- switch (np->g_token) {
- case '*':
- ipar1 = DOUBLE '<'; break;
- case '/':
- ipar1 = DOUBLE '>'; break;
- case ASSIGN '*':
- ipar1 = ASSIGN DOUBLE '<'; break;
- case ASSIGN '/':
- ipar1 = ASSIGN DOUBLE '>'; break;
- default:
- return 0;
- }
-
- l = rp->g_offs;
- if (l < 2 || l > (1<<MAXLOOK))
- return 0;
- i = l;
- for (j=1; j<=MAXLOOK; j++)
- if (i == 1<<j) {
- ipar2 = j;
- return 1;
- }
- return 0;
- }
-
- md_shf(np)
- NODEP np;
- {
- NODEP rp = np->n_right;
-
- np->g_token = ipar1;
- while (rp->g_token == TCONV)
- rp = rp->n_left;
- rp->g_offs = ipar2;
- }
-
- m_fldas(np)
- NODEP np;
- {
- if (np->g_type != E_BIN)
- return 0;
- if (np->g_token == '=' && isfield(np->n_left))
- return 1;
- return 0;
- }
-
- fldas(np)
- register NODEP np;
- {
- NODEP lp = np->n_left;
-
- np->g_fldw = lp->g_fldw;
- np->g_fldo = lp->g_fldo;
- np->g_token = FIELDAS;
-
- lp->g_fldw = 0;
- }
-
- red_con(np)
- register NODEP np;
- {
- while (np->g_token == TCONV)
- np = np->n_left;
- if (np->g_token == ICON || np->g_token == FCON)
- return 1;
- return 0;
- }
-