/* * Fixup struct/unions depending on attributes. */ void gcc_tcattrfix(NODE *p) { struct symtab *sp; struct attr *ap; int sz, coff, csz, al; if ((ap = attr_find(p->n_ap, GCC_ATYP_PACKED)) == NULL) return; /* nothing to fix */ al = ap->iarg(0); /* Must repack struct */ coff = csz = 0; for (sp = strmemb(ap); sp; sp = sp->snext) { if (sp->sclass & FIELD) sz = sp->sclass&FLDSIZ; else sz = (int)tsize(sp->stype, sp->sdf, sp->sap); SETOFF(sz, al); sp->soffset = coff; coff += sz; if (coff > csz) csz = coff; if (p->n_type == UNIONTY) coff = 0; } SETOFF(csz, al); /* Roundup to whatever */ ap = attr_find(p->n_ap, ATTR_BASETYP); ap->atypsz = csz; ap->aalign = al; }
/* * Fixup struct/unions depending on attributes. */ void gcc_tcattrfix(NODE *p) { struct symtab *sp; struct attr *ap; int sz, coff, csz, al, oal, mxal; if (!ISSOU(p->n_type)) /* only for structs or unions */ return; if ((ap = attr_find(p->n_ap, GCC_ATYP_PACKED)) == NULL) return; /* nothing to fix */ al = ap->iarg(0); mxal = 0; /* Must repack struct */ coff = csz = 0; for (sp = strmemb(ap); sp; sp = sp->snext) { oal = talign(sp->stype, sp->sap); if (oal > al) oal = al; if (mxal < oal) mxal = oal; if (sp->sclass & FIELD) sz = sp->sclass&FLDSIZ; else sz = (int)tsize(sp->stype, sp->sdf, sp->sap); sp->soffset = upoff(sz, oal, &coff); if (coff > csz) csz = coff; if (p->n_type == UNIONTY) coff = 0; } if (mxal < ALCHAR) mxal = ALCHAR; /* for bitfields */ SETOFF(csz, mxal); /* Roundup to whatever */ ap = attr_find(p->n_ap, ATTR_STRUCT); ap->amsize = csz; ap = attr_find(p->n_ap, ATTR_ALIGNED); ap->iarg(0) = mxal; }
/* * Watch out for references to static members. */ NODE * cxxstructref(NODE *p, int f, char *n) { struct symtab *sp = strmemb(p->n_ap); if (sp == NULL) cerror("ref to unknown struct"); sp = sfind(n, sp); while (sp != NULL) { if (ISFTN(sp->stype) == 0) { if (sp->sclass == STATIC || sp->sclass == USTATIC) { tfree(p); return nametree(sp); } break; } sp = sfind(n, sp->snext); } return structref(p, f, n); }
/* * local optimizations, most of which are probably * machine independent */ NODE * optim(NODE *p) { int o, ty; NODE *sp, *q; OFFSZ sz; int i; if (odebug) return(p); ty = coptype(p->n_op); if( ty == LTYPE ) return(p); if( ty == BITYPE ) p->n_right = optim(p->n_right); p->n_left = optim(p->n_left); /* collect constants */ again: o = p->n_op; switch(o){ case SCONV: if (concast(p->n_left, p->n_type)) { q = p->n_left; nfree(p); p = q; break; } /* FALLTHROUGH */ case PCONV: if (p->n_type != VOID) p = clocal(p); break; case FORTCALL: p->n_right = fortarg( p->n_right ); break; case ADDROF: if (LO(p) == TEMP) break; if( LO(p) != NAME ) cerror( "& error" ); if( !andable(p->n_left) && !statinit) break; LO(p) = ICON; setuleft: /* paint over the type of the left hand side with the type of the top */ p->n_left->n_type = p->n_type; p->n_left->n_df = p->n_df; p->n_left->n_ap = p->n_ap; q = p->n_left; nfree(p); p = q; break; case NOT: case UMINUS: case COMPL: if (LCON(p) && conval(p->n_left, o, p->n_left)) p = nfree(p); break; case UMUL: /* Do not discard ADDROF TEMP's */ if (LO(p) == ADDROF && LO(p->n_left) != TEMP) { q = p->n_left->n_left; nfree(p->n_left); nfree(p); p = q; break; } if( LO(p) != ICON ) break; LO(p) = NAME; goto setuleft; case RS: if (LCON(p) && RCON(p) && conval(p->n_left, o, p->n_right)) goto zapright; sz = tsize(p->n_type, p->n_df, p->n_ap); if (LO(p) == RS && RCON(p->n_left) && RCON(p) && (RV(p) + RV(p->n_left)) < sz) { /* two right-shift by constants */ RV(p) += RV(p->n_left); p->n_left = zapleft(p->n_left); } #if 0 else if (LO(p) == LS && RCON(p->n_left) && RCON(p)) { RV(p) -= RV(p->n_left); if (RV(p) < 0) o = p->n_op = LS, RV(p) = -RV(p); p->n_left = zapleft(p->n_left); } #endif if (RO(p) == ICON) { if (RV(p) < 0) { RV(p) = -RV(p); p->n_op = LS; goto again; } #ifdef notyet /* must check for side effects, --a >> 32; */ if (RV(p) >= tsize(p->n_type, p->n_df, p->n_sue) && ISUNSIGNED(p->n_type)) { /* ignore signed shifts */ /* too many shifts */ tfree(p->n_left); nfree(p->n_right); p->n_op = ICON; p->n_lval = 0; p->n_sp = NULL; } else #endif /* avoid larger shifts than type size */ if (RV(p) >= sz) { RV(p) = RV(p) % sz; werror("shift larger than type"); } if (RV(p) == 0) p = zapleft(p); } break; case LS: if (LCON(p) && RCON(p) && conval(p->n_left, o, p->n_right)) goto zapright; sz = tsize(p->n_type, p->n_df, p->n_ap); if (LO(p) == LS && RCON(p->n_left) && RCON(p)) { /* two left-shift by constants */ RV(p) += RV(p->n_left); p->n_left = zapleft(p->n_left); } #if 0 else if (LO(p) == RS && RCON(p->n_left) && RCON(p)) { RV(p) -= RV(p->n_left); p->n_left = zapleft(p->n_left); } #endif if (RO(p) == ICON) { if (RV(p) < 0) { RV(p) = -RV(p); p->n_op = RS; goto again; } #ifdef notyet /* must check for side effects */ if (RV(p) >= tsize(p->n_type, p->n_df, p->n_sue)) { /* too many shifts */ tfree(p->n_left); nfree(p->n_right); p->n_op = ICON; p->n_lval = 0; p->n_sp = NULL; } else #endif /* avoid larger shifts than type size */ if (RV(p) >= sz) { RV(p) = RV(p) % sz; werror("shift larger than type"); } if (RV(p) == 0) p = zapleft(p); } break; case MINUS: if (LCON(p) && RCON(p) && p->n_left->n_sp == p->n_right->n_sp) { /* link-time constants, but both are the same */ /* solve it now by forgetting the symbols */ p->n_left->n_sp = p->n_right->n_sp = NULL; } if( !nncon(p->n_right) ) break; RV(p) = -RV(p); o = p->n_op = PLUS; case MUL: /* * Check for u=(x-y)+z; where all vars are pointers to * the same struct. This has two advantages: * 1: avoid a mul+div * 2: even if not allowed, people may get surprised if this * calculation do not give correct result if using * unaligned structs. */ if (p->n_type == INTPTR && RCON(p) && LO(p) == DIV && RCON(p->n_left) && RV(p) == RV(p->n_left) && LO(p->n_left) == MINUS) { q = p->n_left->n_left; if (q->n_left->n_type == PTR+STRTY && q->n_right->n_type == PTR+STRTY && strmemb(q->n_left->n_ap) == strmemb(q->n_right->n_ap)) { p = zapleft(p); p = zapleft(p); } } /* FALLTHROUGH */ case PLUS: case AND: case OR: case ER: /* commutative ops; for now, just collect constants */ /* someday, do it right */ if( nncon(p->n_left) || ( LCON(p) && !RCON(p) ) ) SWAP( p->n_left, p->n_right ); /* make ops tower to the left, not the right */ if( RO(p) == o ){ NODE *t1, *t2, *t3; t1 = p->n_left; sp = p->n_right; t2 = sp->n_left; t3 = sp->n_right; /* now, put together again */ p->n_left = sp; sp->n_left = t1; sp->n_right = t2; sp->n_type = p->n_type; p->n_right = t3; } if(o == PLUS && LO(p) == MINUS && RCON(p) && RCON(p->n_left) && conval(p->n_right, MINUS, p->n_left->n_right)){ zapleft: q = p->n_left->n_left; nfree(p->n_left->n_right); nfree(p->n_left); p->n_left = q; } if( RCON(p) && LO(p)==o && RCON(p->n_left) && conval( p->n_right, o, p->n_left->n_right ) ){ goto zapleft; } else if( LCON(p) && RCON(p) && conval( p->n_left, o, p->n_right ) ){ zapright: nfree(p->n_right); q = makety(p->n_left, p->n_type, p->n_qual, p->n_df, p->n_ap); nfree(p); p = clocal(q); break; } /* change muls to shifts */ if( o == MUL && nncon(p->n_right) && (i=ispow2(RV(p)))>=0){ if( i == 0 ) { /* multiplication by 1 */ goto zapright; } o = p->n_op = LS; p->n_right->n_type = INT; p->n_right->n_df = NULL; RV(p) = i; } /* change +'s of negative consts back to - */ if( o==PLUS && nncon(p->n_right) && RV(p)<0 ){ RV(p) = -RV(p); o = p->n_op = MINUS; } /* remove ops with RHS 0 */ if ((o == PLUS || o == MINUS || o == OR || o == ER) && nncon(p->n_right) && RV(p) == 0) { goto zapright; } break; case DIV: if( nncon( p->n_right ) && p->n_right->n_lval == 1 ) goto zapright; if (LCON(p) && RCON(p) && conval(p->n_left, DIV, p->n_right)) goto zapright; if (RCON(p) && ISUNSIGNED(p->n_type) && (i=ispow2(RV(p))) > 0) { p->n_op = RS; RV(p) = i; q = p->n_right; if(tsize(q->n_type, q->n_df, q->n_ap) > SZINT) p->n_right = makety(q, INT, 0, 0, 0); break; } break; case MOD: if (RCON(p) && ISUNSIGNED(p->n_type) && ispow2(RV(p)) > 0) { p->n_op = AND; RV(p) = RV(p) -1; break; } break; case EQ: case NE: case LT: case LE: case GT: case GE: case ULT: case ULE: case UGT: case UGE: if( !LCON(p) ) break; /* exchange operands */ sp = p->n_left; p->n_left = p->n_right; p->n_right = sp; p->n_op = revrel[p->n_op - EQ ]; break; #ifdef notyet case ASSIGN: /* Simple test to avoid two branches */ if (RO(p) != NE) break; q = p->n_right; if (RCON(q) && RV(q) == 0 && LO(q) == AND && RCON(q->n_left) && (i = ispow2(RV(q->n_left))) && q->n_left->n_type == INT) { q->n_op = RS; RV(q) = i; } break; #endif } return(p); }