/* * Copyright (c) 2008 David Crawshaw * * 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, MKAP(INT)); 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) { }