}
}
+void ppIRDefault ( IRDefault dflt )
+{
+ switch (dflt) {
+ case Idflt_None: vex_printf("Dflt-None"); return;
+ case Idflt_Zeroes: vex_printf("Dflt-Zero"); return;
+ case Idflt_Ones: vex_printf("Dflt-One"); return;
+ default: vpanic("ppIRDefault");
+ }
+}
+
void ppIRDirty ( IRDirty* d )
{
Int i;
ppIRTemp(d->tmp);
vex_printf(" = ");
}
+ if (d->dflt != Idflt_None) {
+ vex_printf("(");
+ ppIRDefault(d->dflt);
+ vex_printf(") ");
+ }
vex_printf("DIRTY ");
ppIRExpr(d->guard);
if (d->needsBBP)
d->guard = NULL;
d->args = NULL;
d->tmp = IRTemp_INVALID;
+ d->dflt = Idflt_None;
d->mFx = Ifx_None;
d->mAddr = NULL;
d->mSize = 0;
d2->guard = deepCopyIRExpr(d->guard);
d2->args = deepCopyIRExprVec(d->args);
d2->tmp = d->tmp;
+ d2->dflt = d->dflt;
d2->mFx = d->mFx;
d2->mAddr = d->mAddr==NULL ? NULL : deepCopyIRExpr(d->mAddr);
d2->mSize = d->mSize;
if (typeOfIRExpr(tyenv, d->args[i]) == Ity_I1)
sanityCheckFail(bb,stmt,"IRStmt.Dirty.arg[i] :: Ity_I1");
}
+ /* if the call returns a value and isn't obviously
+ unconditional, check there's a reasonable default-spec for
+ the return value. */
+ if (d->tmp != IRTemp_INVALID) {
+ IRExpr* guard = d->guard;
+ Bool obviouslyUncond = False;
+ if (guard->tag == Iex_Const
+ && guard->Iex.Const.con->tag == Ico_U1
+ && guard->Iex.Const.con->Ico.U1 == True) {
+ obviouslyUncond = True;
+ }
+ if (!obviouslyUncond
+ && d->dflt != Idflt_Ones && d->dflt != Idflt_Zeroes)
+ goto bad_dirty;
+ }
break;
bad_dirty:
sanityCheckFail(bb,stmt,"IRStmt.Dirty: ill-formed");
call does not access guest state.
IMPORTANT NOTE re GUARDS: Dirty calls are strict, very strict. The
- arguments, and 'mFx' are evaluated REGARDLESS of the guard value.
- The order of argument evaluation is unspecified. The guard
+ arguments and 'mFx' are evaluated REGARDLESS of the guard value.
+ The order of argument evaluation is unspecified. The guard
expression is evaluated AFTER the arguments and 'mFx' have been
evaluated. 'mFx' is expected (by Memcheck) to be a defined value
even if the guard evaluates to false.
/* Pretty-print an IREffect */
extern void ppIREffect ( IREffect );
+/* Default values for guarded dirty calls which return a result. */
+typedef
+ enum {
+ Idflt_None=0x1B80, /* default unspecified */
+ Idflt_Zeroes, /* all zeroes */
+ Idflt_Ones /* all ones */
+ }
+ IRDefault;
+
+/* Pretty-print an IRDefault */
+extern void ppIRDefault ( IRDefault );
typedef
struct _IRDirty {
/* What to call, and details of args/results. .guard must be
non-NULL. If .tmp is not IRTemp_INVALID, then the call
returns a result which is placed in .tmp. If at runtime the
- guard evaluates to false, .tmp has an all-ones bit pattern
- written to it. Hence conditional calls that assign .tmp are
- allowed. */
+ guard evaluates to false, .tmp has an all-zeroes or all-ones
+ bit pattern written to it, as specified by .dflt. Hence
+ conditional calls that assign .tmp are allowed. */
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 IRTemp_INVALID if none */
+ IRDefault dflt; /* for result, if guarded and tmp != INVALID */
/* Mem effects; we allow only one R/W/M region to be stated */
IREffect mFx; /* indicates memory effects, if any */