]> git.ipfire.org Git - thirdparty/valgrind.git/commitdiff
IR: add the ability to specify the call-didn't-happen ("default")
authorJulian Seward <jseward@acm.org>
Mon, 17 Dec 2012 21:54:10 +0000 (21:54 +0000)
committerJulian Seward <jseward@acm.org>
Mon, 17 Dec 2012 21:54:10 +0000 (21:54 +0000)
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

VEX/priv/ir_defs.c
VEX/pub/libvex_ir.h

index fe8c3e9d552aa869d9341454247e1012ece64c5c..b7e05a27c0ea6e8a164d48f3388fe6ec6707be12 100644 (file)
@@ -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");
index 1a7a4d11bd667c2121663b8520c138bfe3dce13b..4b162e4fae0d0249aeb672273ffe252efa911287 100644 (file)
@@ -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 */