void param_hydrate(param_t **pp) { param_t *p; assert(pp); if (isdehydrated(*pp)) { while (*pp) { assert(isdehydrated(*pp)); p = (param_t *) ph_hydrate(pp); param_debug(p); type_hydrate(&p->Ptype); if (p->Ptype) type_debug(p->Ptype); ph_hydrate(&p->Pident); if (CPP) { el_hydrate(&p->Pelem); if (p->Pelem) elem_debug(p->Pelem); type_hydrate(&p->Pdeftype); if (p->Pptpl) param_hydrate(&p->Pptpl); if (p->Psym) symbol_hydrate(&p->Psym); if (p->PelemToken) token_hydrate(&p->PelemToken); } pp = &p->Pnext; } } }
void el_setVolatile(elem *e) { elem_debug(e); while (1) { e->Ety |= mTYvolatile; if (OTunary(e->Eoper)) e = e->E1; else if (OTbinary(e->Eoper)) { el_setVolatile(e->E2); e = e->E1; } else break; } }
elem *exp2_copytotemp(elem *e) { //printf("exp2_copytotemp()\n"); elem_debug(e); Symbol *stmp = symbol_genauto(e); elem *eeq = el_bin(OPeq,e->Ety,el_var(stmp),e); elem *er = el_bin(OPcomma,e->Ety,eeq,el_var(stmp)); if (tybasic(e->Ety) == TYstruct || tybasic(e->Ety) == TYarray) { eeq->Eoper = OPstreq; eeq->ET = e->ET; eeq->E1->ET = e->ET; er->ET = e->ET; er->E2->ET = e->ET; } return er; }
STATIC unsigned cs_comphash(elem *e) { register int hash; unsigned op; elem_debug(e); op = e->Eoper; #if TX86 hash = (e->Ety & (mTYbasic | mTYconst | mTYvolatile)) + (op << 8); #else hash = e->Ety + op; #endif if (!OTleaf(op)) { hash += (size_t) e->E1; if (OTbinary(op)) hash += (size_t) e->E2; } else { hash += e->EV.Vint; if (op == OPvar || op == OPrelconst) hash += (size_t) e->EV.sp.Vsym; } return hash; }
void param_hydrate(param_t **pp) { param_t *p; assert(pp); if (isdehydrated(*pp)) { while (*pp) { assert(isdehydrated(*pp)); p = (param_t *) ph_hydrate(pp); #if SOURCE_4PARAMS p->Psrcpos.Sfilnum += File_Hydrate_Num; /* file number relative header build */ #endif param_debug(p); type_hydrate(&p->Ptype); if (p->Ptype) type_debug(p->Ptype); ph_hydrate(&p->Pident); if (CPP) { el_hydrate(&p->Pelem); if (p->Pelem) elem_debug(p->Pelem); type_hydrate(&p->Pdeftype); if (p->Pptpl) param_hydrate(&p->Pptpl); if (p->Psym) symbol_hydrate(&p->Psym); if (p->PelemToken) token_hydrate(&p->PelemToken); } pp = &p->Pnext; } } }
STATIC void ecom(elem **pe) { int i,op,hcstopsave; unsigned hash; elem *e,*ehash; tym_t tym; e = *pe; assert(e); elem_debug(e); #ifdef DEBUG assert(e->Ecount == 0); //assert(e->Ecomsub == 0); #endif tym = tybasic(e->Ety); op = e->Eoper; switch (op) { case OPconst: case OPvar: case OPrelconst: break; case OPstreq: case OPpostinc: case OPpostdec: case OPeq: case OPaddass: case OPminass: case OPmulass: case OPdivass: case OPmodass: case OPshrass: case OPashrass: case OPshlass: case OPandass: case OPxorass: case OPorass: #if TX86 /* Reverse order of evaluation for double op=. This is so that */ /* the pushing of the address of the second operand is easier. */ /* However, with the 8087 we don't need the kludge. */ if (op != OPeq && tym == TYdouble && !config.inline8087) { if (EOP(e->E1)) ecom(&e->E1->E1); ecom(&e->E2); } else #endif { /* Don't mark the increment of an i++ or i-- as a CSE, if it */ /* can be done with an INC or DEC instruction. */ if (!(OTpost(op) && elemisone(e->E2))) ecom(&e->E2); /* evaluate 2nd operand first */ case OPnegass: if (EOP(e->E1)) /* if lvalue is an operator */ { #ifdef DEBUG if (e->E1->Eoper != OPind) elem_print(e); #endif assert(e->E1->Eoper == OPind); ecom(&(e->E1->E1)); } } touchlvalue(e->E1); if (!OTpost(op)) /* lvalue of i++ or i-- is not a cse*/ { hash = cs_comphash(e->E1); vec_setbit(hash % CSVECDIM,csvec); addhcstab(e->E1,hash); // add lvalue to hcstab[] } return; case OPbtc: case OPbts: case OPbtr: ecom(&e->E1); ecom(&e->E2); touchfunc(0); // indirect assignment return; case OPandand: case OPoror: ecom(&e->E1); hcstopsave = hcstop; ecom(&e->E2); hcstop = hcstopsave; /* no common subs by E2 */ return; /* if comsub then logexp() will */ /* break */ case OPcond: ecom(&e->E1); hcstopsave = hcstop; ecom(&e->E2->E1); /* left condition */ hcstop = hcstopsave; /* no common subs by E2 */ ecom(&e->E2->E2); /* right condition */ hcstop = hcstopsave; /* no common subs by E2 */ return; /* can't be a common sub */ case OPcall: case OPcallns: ecom(&e->E2); /* eval right first */ /* FALL-THROUGH */ case OPucall: case OPucallns: ecom(&e->E1); touchfunc(1); return; case OPstrpar: /* so we don't break logexp() */ #if TX86 case OPinp: /* never CSE the I/O instruction itself */ #endif case OPdctor: ecom(&e->E1); /* FALL-THROUGH */ case OPasm: case OPstrthis: // don't CSE these case OPframeptr: case OPgot: case OPctor: case OPdtor: case OPmark: return; case OPddtor: return; case OPparam: #if TX86 case OPoutp: #endif ecom(&e->E1); case OPinfo: ecom(&e->E2); return; case OPcomma: case OPremquo: ecom(&e->E1); ecom(&e->E2); break; #if TARGET_SEGMENTED case OPvp_fp: case OPcvp_fp: ecom(&e->E1); touchaccess(e); break; #endif case OPind: ecom(&e->E1); /* Generally, CSEing a *(double *) results in worse code */ if (tyfloating(tym)) return; break; #if TX86 case OPstrcpy: case OPstrcat: case OPmemcpy: case OPmemset: ecom(&e->E2); case OPsetjmp: ecom(&e->E1); touchfunc(0); return; #endif default: /* other operators */ #if TX86 #ifdef DEBUG if (!EBIN(e)) WROP(e->Eoper); #endif assert(EBIN(e)); case OPadd: case OPmin: case OPmul: case OPdiv: case OPor: case OPxor: case OPand: case OPeqeq: case OPne: case OPscale: case OPyl2x: case OPyl2xp1: ecom(&e->E1); ecom(&e->E2); break; #else #ifdef DEBUG if (!EOP(e)) WROP(e->Eoper); #endif assert(EOP(e)); ecom(&e->E1); if (EBIN(e)) ecom(&e->E2); /* eval left first */ break; #endif case OPstring: case OPaddr: case OPbit: #ifdef DEBUG WROP(e->Eoper); elem_print(e); #endif assert(0); /* optelem() should have removed these */ /* NOTREACHED */ // Explicitly list all the unary ops for speed case OPnot: case OPcom: case OPneg: case OPuadd: case OPabs: case OPsqrt: case OPrndtol: case OPsin: case OPcos: case OPrint: case OPpreinc: case OPpredec: case OPbool: case OPstrlen: case OPs16_32: case OPu16_32: case OPd_s32: case OPd_u32: case OPs32_d: case OPu32_d: case OPd_s16: case OPs16_d: case OP32_16: case OPd_f: case OPf_d: case OPd_ld: case OPld_d: case OPc_r: case OPc_i: case OPu8_16: case OPs8_16: case OP16_8: case OPu32_64: case OPs32_64: case OP64_32: case OPmsw: case OPu64_128: case OPs64_128: case OP128_64: case OPd_s64: case OPs64_d: case OPd_u64: case OPu64_d: case OPstrctor: case OPu16_d: case OPd_u16: case OParrow: case OPvoid: case OPnullcheck: case OPbsf: case OPbsr: case OPbswap: case OPld_u64: #if TARGET_SEGMENTED case OPoffset: case OPnp_fp: case OPnp_f16p: case OPf16p_np: #endif ecom(&e->E1); break; case OPhalt: return; } /* don't CSE structures or unions or volatile stuff */ if (tym == TYstruct || tym == TYvoid || e->Ety & mTYvolatile #if TX86 // don't CSE doubles if inline 8087 code (code generator can't handle it) || (tyfloating(tym) && config.inline8087) #endif ) return; hash = cs_comphash(e); /* must be AFTER leaves are done */ /* Search for a match in hcstab[]. * Search backwards, as most likely matches will be towards the end * of the list. */ #ifdef DEBUG if (debugx) dbg_printf("elem: %p hash: %6d\n",e,hash); #endif int csveci = hash % CSVECDIM; if (vec_testbit(csveci,csvec)) { for (i = hcstop; i--;) { #ifdef DEBUG if (debugx) dbg_printf("i: %2d Hhash: %6d Helem: %p\n", i,hcstab[i].Hhash,hcstab[i].Helem); #endif if (hash == hcstab[i].Hhash && (ehash = hcstab[i].Helem) != NULL) { /* if elems are the same and we still have room for more */ if (el_match(e,ehash) && ehash->Ecount < 0xFF) { /* Make sure leaves are also common subexpressions * to avoid false matches. */ if (!OTleaf(op)) { if (!e->E1->Ecount) continue; if (OTbinary(op) && !e->E2->Ecount) continue; } ehash->Ecount++; *pe = ehash; #ifdef DEBUG if (debugx) dbg_printf("**MATCH** %p with %p\n",e,*pe); #endif el_free(e); return; } } } } else vec_setbit(csveci,csvec); addhcstab(e,hash); // add this elem to hcstab[] }