void ppIRDirty ( IRDirty* d )
{
Int i;
- vex_printf("DIRTY");
+ vex_printf("DIRTY ");
+ ppIRExpr(d->guard);
if (d->needsBBP)
vex_printf(" NeedsBBP");
if (d->mFx != Ifx_None) {
IRDirty* emptyIRDirty ( void ) {
IRDirty* d = LibVEX_Alloc(sizeof(IRDirty));
d->cee = NULL;
+ d->guard = NULL;
d->args = NULL;
d->tmp = INVALID_IRTEMP;
d->mFx = Ifx_None;
Int i;
IRDirty* d2 = emptyIRDirty();
d2->cee = dopyIRCallee(d->cee);
+ d2->guard = dopyIRExpr(d->guard);
d2->args = dopyIRExprVec(d->args);
d2->tmp = d->tmp;
d2->mFx = d->mFx;
if (d->fxState[i].size <= 0) goto bad_dirty;
}
/* check types, minimally */
+ if (d->guard == NULL) goto bad_dirty;
+ if (typeOfIRExpr(tyenv, d->guard) != Ity_Bit)
+ sanityCheckFail(bb,stmt,"IRStmt.Dirty.guard not :: Ity_Bit");
if (d->tmp != INVALID_IRTEMP
&& typeOfIRTemp(tyenv, d->tmp) == Ity_Bit)
sanityCheckFail(bb,stmt,"IRStmt.Dirty.dst :: Ity_Bit");
IRExpr** args )
{
IRDirty* d = emptyIRDirty();
- d->cee = mkIRCallee ( regparms, name, addr );
- d->args = args;
+ d->cee = mkIRCallee ( regparms, name, addr );
+ d->guard = IRExpr_Const(IRConst_Bit(True));
+ d->args = args;
return d;
}
IRExpr** args )
{
IRDirty* d = emptyIRDirty();
- d->cee = mkIRCallee ( regparms, name, addr );
- d->args = args;
- d->tmp = dst;
+ d->cee = mkIRCallee ( regparms, name, addr );
+ d->guard = IRExpr_Const(IRConst_Bit(True));
+ d->args = args;
+ d->tmp = dst;
return d;
}
}
-#if 0
-/* Apparently unused */
-/* Delete any binding for key in h. */
-
-static void delFromHHW ( HashHW* h, HWord key )
-{
- Int i;
- for (i = 0; i < h->used; i++) {
- if (h->inuse[i] && h->key[i] == key) {
- h->inuse[i] = False;
- return;
- }
- }
-}
-#endif
-
-
/* Add key->val to the map. Replaces any existing binding for key. */
static void addToHHW ( HashHW* h, HWord key, HWord val )
} else {
vassert(d2->mAddr == NULL);
}
+ d2->guard = flatten_Expr(bb, d2->guard);
for (i = 0; d2->args[i]; i++)
d2->args[i] = flatten_Expr(bb, d2->args[i]);
addStmtToIRBB(bb, IRStmt_Dirty(d2));
vassert(isAtom(d2->mAddr));
d2->mAddr = fold_Expr(subst_Expr(env, d2->mAddr));
}
+ vassert(isAtom(d2->guard));
+ d2->guard = fold_Expr(subst_Expr(env, d2->guard));
for (i = 0; d2->args[i]; i++) {
vassert(isAtom(d2->args[i]));
d2->args[i] = fold_Expr(subst_Expr(env, d2->args[i]));
d = st->Ist.Dirty.details;
if (d->mFx != Ifx_None)
addUses_Expr(set, d->mAddr);
+ addUses_Expr(set, d->guard);
for (i = 0; d->args[i] != NULL; i++)
addUses_Expr(set, d->args[i]);
return;
d = st->Ist.Dirty.details;
if (d->mFx != Ifx_None)
occCount_Expr(env, d->mAddr);
+ occCount_Expr(env, d->guard);
for (i = 0; d->args[i]; i++)
occCount_Expr(env, d->args[i]);
return;
*d2 = *d;
if (d2->mFx != Ifx_None)
d2->mAddr = tbSubst_Expr(env, d2->mAddr);
+ d2->guard = tbSubst_Expr(env, d2->guard);
for (i = 0; d2->args[i]; i++)
d2->args[i] = tbSubst_Expr(env, d2->args[i]);
return IRStmt_Dirty(d2);
break;
case Ist_Dirty:
d = st->Ist.Dirty.details;
+ deltaIRExpr(d->guard, delta);
for (i = 0; d->args[i]; i++)
deltaIRExpr(d->args[i], delta);
if (d->tmp != INVALID_IRTEMP)
break;
case Ist_Dirty:
d = st->Ist.Dirty.details;
+ vassert(isAtom(d->guard));
for (j = 0; d->args[j]; j++)
vassert(isAtom(d->args[j]));
if (d->mFx != Ifx_None)
access the guest state. It is invalid for .nFxState to be zero
but .needsBBP to be True, since .nFxState==0 is a claim that the
call does not access guest state.
+
+ IMPORTANT NOTE re GUARDS: Dirty calls are strict, very strict. The
+ arguments are evaluated REGARDLESS of the guard value. It is
+ unspecified the relative order of arg evaluation and guard
+ evaluation.
*/
#define VEX_N_FXSTATE 4 /* enough for CPUID on x86 */
struct {
/* What to call, and details of args/results */
IRCallee* cee; /* where to call */
+ IRExpr* guard; /* :: Ity_Bit. Controls whether call happens */
IRExpr** args; /* arg list, ends in NULL */
IRTemp tmp; /* to assign result to, or INVALID_IRTEMP if none */
/* A handy function which takes some of the tedium out of constructing
dirty helper calls. The called function impliedly does not return
- any value. The call is marked as accessing neither guest state nor
- memory (hence the "unsafe" designation) -- you can mess with this
- later if need be. A suitable IRCallee is constructed from the
- supplied bits. */
+ any value and has a constant-True guard. The call is marked as
+ accessing neither guest state nor memory (hence the "unsafe"
+ designation) -- you can mess with this later if need be. A
+ suitable IRCallee is constructed from the supplied bits. */
extern
IRDirty* unsafeIRDirty_0_N ( Int regparms, Char* name, void* addr,
IRExpr** args );