Logo Search packages:      
Sourcecode: pcc version File versions  Download package

local.c

/*
 * Copyright (c) 2008 David Crawshaw <david@zentus.com>
 * 
 * Permission to use, copy, modify, and/or distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 * 
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

#include "pass1.h"

NODE *
clocal(NODE *p)
{
      struct symtab *sp;
      int op;
      NODE *r, *l;

      op = p->n_op;
      sp = p->n_sp;
      l  = p->n_left;
      r  = p->n_right;

#ifdef PCC_DEBUG
      if (xdebug) {
            printf("clocal in: %p, %s\n", p, copst(op));
            fwalk(p, eprint, 0);
      }
#endif

      switch (op) {

      case NAME:
            if (sp->sclass == PARAM || sp->sclass == AUTO) {
                  /*
                   * Use a fake structure reference to
                   * write out frame pointer offsets.
                   */
                  l = block(REG, NIL, NIL, PTR+STRTY, 0, 0);
                  l->n_lval = 0;
                  l->n_rval = FP;
                  r = p;
                  p = stref(block(STREF, l, r, 0, 0, 0));
            }
            break;
      case PCONV: /* Remove what PCONVs we can. */
            if (l->n_op == SCONV)
                  break;

            if (l->n_op == ICON || (ISPTR(p->n_type) && ISPTR(l->n_type))) {
                  l->n_type = p->n_type;
                  l->n_qual = p->n_qual;
                  l->n_df = p->n_df;
                  l->n_ap = p->n_ap;
                  nfree(p);
                  p = l;
            }
            break;

      case SCONV:
        /* Remove redundant conversions. */
            if ((p->n_type & TMASK) == 0 && (l->n_type & TMASK) == 0 &&
                btattr[p->n_type].atypsz == btattr[l->n_type].atypsz &&
                p->n_type != FLOAT && p->n_type != DOUBLE &&
                l->n_type != FLOAT && l->n_type != DOUBLE &&
                l->n_type != DOUBLE && p->n_type != LDOUBLE) {
                  if (l->n_op == NAME || l->n_op == UMUL ||
                      l->n_op == TEMP) {
                        l->n_type = p->n_type;
                        nfree(p);
                        p = l;
                        break;
                  }
            }

        /* Convert floating point to int before to char or short. */
        if ((l->n_type == FLOAT || l->n_type == DOUBLE || l->n_type == LDOUBLE)
            && (DEUNSIGN(p->n_type) == CHAR || DEUNSIGN(p->n_type) == SHORT)) {
            p = block(SCONV, p, NIL, p->n_type, p->n_df, p->n_ap);
            p->n_left->n_type = INT;
            break;
        }

        /* Transform constants now. */
            if (l->n_op != ICON)
                  break;

            if (ISPTR(p->n_type)) {
                  l->n_type = p->n_type;
                  nfree(p);
                  p = l;
                  break;
            }

            switch (p->n_type) {
            case BOOL:      l->n_lval = (l->n_lval != 0); break;
            case CHAR:      l->n_lval = (char)l->n_lval; break;
            case UCHAR:     l->n_lval = l->n_lval & 0377; break;
            case SHORT:     l->n_lval = (short)l->n_lval; break;
            case USHORT:    l->n_lval = l->n_lval & 0177777; break;
            case UNSIGNED:  l->n_lval = l->n_lval & 0xffffffff; break;
            case INT:       l->n_lval = (int)l->n_lval; break;
            case ULONG:
            case ULONGLONG: l->n_lval = l->n_lval; break;
            case LONG:
            case LONGLONG:    l->n_lval = (long long)l->n_lval; break;
            case FLOAT:
            case DOUBLE:
            case LDOUBLE:
                  l->n_op = FCON;
                  l->n_dcon = l->n_lval;
                  break;
            case VOID:
                  break;
            default:
                  cerror("sconv type unknown %d", p->n_type);
            }

            l->n_type = p->n_type;
            nfree(p);
            p = l;
            break;

      case PMCONV:
      case PVCONV:
            if (r->n_op != ICON)
                  cerror("converting bad type");
            nfree(p);
            p = buildtree(op == PMCONV ? MUL : DIV, l, r);
            break;

      case FORCE:
            /* Put attached value into the return register. */
            p->n_op = ASSIGN;
            p->n_right = p->n_left;
            p->n_left = block(REG, NIL, NIL, p->n_type, 0, 0);
            p->n_left->n_rval = RETREG_PRE(p->n_type);
            break;
      }

#ifdef PCC_DEBUG
      if (xdebug) {
            printf("clocal out: %p, %s\n", p, copst(op));
            fwalk(p, eprint, 0);
      }
#endif

      return p;
}

void
myp2tree(NODE *p)
{
      struct symtab *sp;

      if (p->n_op != FCON)
            return;

      sp = tmpalloc(sizeof(struct symtab));
      sp->sclass = STATIC;
      sp->slevel = 1;
      sp->soffset = getlab();
      sp->sflags = 0;
      sp->stype = p->n_type;
      sp->squal = (CON >> TSHIFT);

      defloc(sp);
      ninval(0, btattr[p->n_type].atypsz, p);

      p->n_op = NAME;
      p->n_lval = 0;
      p->n_sp = sp;
}

int
andable(NODE *p)
{
      return 1;
}

void
cendarg()
{
      autooff = AUTOINIT;
}

int
cisreg(TWORD t)
{
      /* SPARCv9 registers are all 64-bits wide. */
      return 1;
}

NODE *
offcon(OFFSZ off, TWORD t, union dimfun *d, struct attr *ap)
{
      return bcon(off / SZCHAR);
}

void
spalloc(NODE *t, NODE *p, OFFSZ off)
{
}

void
instring(struct symtab *sp)
{
      char *s, *str;

      defloc(sp);
      str = sp->sname;

      printf("\t.ascii \"");
      for (s = str; *s != 0; ) {
            if (*s++ == '\\')
                  esccon(&s);
            if (s - str > 60) {
                  fwrite(str, 1, s - str, stdout);
                  printf("\"\n\t.ascii \"");
                  str = s;
            }
      }
      fwrite(str, 1, s - str, stdout);
      printf("\\0\"\n");
}

void
zbits(OFFSZ off, int fsz)
{
}

void
infld(CONSZ off, int fsz, CONSZ val)
{
}

void
ninval(CONSZ off, int fsz, NODE *p)
{
      TWORD t;
      struct symtab *sp;
      union { float f; double d; int i; long long l; } u;

      t = p->n_type;
      sp = p->n_sp;

      if (ISPTR(t))
            t = LONGLONG;

      if (p->n_op != ICON && p->n_op != FCON)
            cerror("ninval: not a constant");
      if (p->n_op == ICON && sp != NULL && DEUNSIGN(t) != LONGLONG)
            cerror("ninval: not constant");

      switch (t) {
            case CHAR:
            case UCHAR:
                  printf("\t.byte %d\n", (int)p->n_lval & 0xff);
                  break;
            case SHORT:
            case USHORT:
                  printf("\t.half %d\n", (int)p->n_lval &0xffff);
                  break;
            case BOOL:
                  p->n_lval = (p->n_lval != 0); /* FALLTHROUGH */
            case INT:
            case UNSIGNED:
                  printf("\t.long " CONFMT "\n", p->n_lval);
                  break;
            case LONG:
            case ULONG:
            case LONGLONG:
            case ULONGLONG:
                  printf("\t.xword %lld", p->n_lval);
                  if (sp != 0) {
                        if (sp->sclass == STATIC && sp->slevel > 0)
                              printf("+" LABFMT, sp->soffset);
                        else
                              printf("+%s", sp->soname ?
                                  sp->soname : exname(sp->sname));
                  }
                  printf("\n");
                  break;
            case FLOAT:
                  u.f = (float)p->n_dcon;
                  printf("\t.long %d\n", u.i);
                  break;
            case DOUBLE:
                  u.d = (double)p->n_dcon;
                  printf("\t.xword %lld\n", u.l);
                  break;
      }
}

char *
exname(char *p)
{
      return p ? p : "";
}

TWORD
ctype(TWORD type)
{
      return type;
}

void
calldec(NODE *p, NODE *q) 
{
}

void
extdec(struct symtab *q)
{
}

void
defzero(struct symtab *sp)
{
      int off = (tsize(sp->stype, sp->sdf, sp->sap) + SZCHAR - 1) / SZCHAR;
      printf("\t.comm ");
      if (sp->slevel == 0)
            printf("%s,%d\n", sp->soname ? sp->soname : exname(sp->sname), off);
      else
            printf(LABFMT ",%d\n", sp->soffset, off);
}

int
mypragma(char *str)
{
      return 0;
}

void
fixdef(struct symtab *sp)
{
}

void
pass1_lastchance(struct interpass *ip)
{
}


Generated by  Doxygen 1.6.0   Back to index