From: Julian Seward Date: Mon, 17 Dec 2012 21:54:10 +0000 (+0000) Subject: IR: add the ability to specify the call-didn't-happen ("default") X-Git-Tag: svn/VALGRIND_3_9_0^2~152^2~10 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=a917679ee188c9d4a3ac30d2dc51ec9be7b95e4e;p=thirdparty%2Fvalgrind.git IR: add the ability to specify the call-didn't-happen ("default") return value for conditional dirty helper calls returning values. The default value can be either all-zeroes or all-ones. git-svn-id: svn://svn.valgrind.org/vex/branches/COMEM@2594 --- diff --git a/VEX/priv/ir_defs.c b/VEX/priv/ir_defs.c index fe8c3e9d55..b7e05a27c0 100644 --- a/VEX/priv/ir_defs.c +++ b/VEX/priv/ir_defs.c @@ -1140,6 +1140,16 @@ void ppIREffect ( IREffect fx ) } } +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; @@ -1147,6 +1157,11 @@ void ppIRDirty ( IRDirty* d ) 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) @@ -1738,6 +1753,7 @@ IRDirty* emptyIRDirty ( void ) { d->guard = NULL; d->args = NULL; d->tmp = IRTemp_INVALID; + d->dflt = Idflt_None; d->mFx = Ifx_None; d->mAddr = NULL; d->mSize = 0; @@ -2074,6 +2090,7 @@ IRDirty* deepCopyIRDirty ( IRDirty* d ) 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; @@ -3874,6 +3891,21 @@ void tcStmt ( IRSB* bb, IRStmt* stmt, IRType gWordTy ) 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"); diff --git a/VEX/pub/libvex_ir.h b/VEX/pub/libvex_ir.h index 1a7a4d11bd..4b162e4fae 100644 --- a/VEX/pub/libvex_ir.h +++ b/VEX/pub/libvex_ir.h @@ -1936,8 +1936,8 @@ extern void ppIRJumpKind ( IRJumpKind ); 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. @@ -1958,19 +1958,31 @@ typedef /* 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 */