]> git.ipfire.org Git - thirdparty/valgrind.git/commitdiff
Finish off Memcheck's handling of dirty helper calls. Memcheck is now
authorJulian Seward <jseward@acm.org>
Wed, 10 Nov 2004 12:07:51 +0000 (12:07 +0000)
committerJulian Seward <jseward@acm.org>
Wed, 10 Nov 2004 12:07:51 +0000 (12:07 +0000)
feature-complete (!)

git-svn-id: svn://svn.valgrind.org/vex/trunk@534

VEX/head20041019/memcheck/mc_translate.c

index 3e59adeb87849decca854e5f3c82d1deaab30c6e..e405875045578a384a6c1f82c0e5a9ded44827c2 100644 (file)
@@ -1032,6 +1032,7 @@ IRExpr* expr2vbits_Unop ( MCEnv* mce, IROp op, IRAtom* atom )
          return assignNew(mce, Ity_Bit, unop(Iop_32to1, vatom));
 
       case Iop_ReinterpF64asI64:
+      case Iop_ReinterpI64asF64:
       case Iop_Not32:
       case Iop_Not16:
       case Iop_Not8:
@@ -1045,12 +1046,13 @@ IRExpr* expr2vbits_Unop ( MCEnv* mce, IROp op, IRAtom* atom )
 
 
 static
-IRAtom* expr2vbits_LDle ( MCEnv* mce, IRType ty, IRAtom* addr )
+IRAtom* expr2vbits_LDle ( MCEnv* mce, IRType ty, IRAtom* addr, UInt bias )
 {
    void*    helper;
    Char*    hname;
    IRDirty* di;
    IRTemp   datavbits;
+   IRAtom*  addrAct;
 
    sk_assert(isOriginalAtom(mce,addr));
 
@@ -1078,11 +1080,23 @@ IRAtom* expr2vbits_LDle ( MCEnv* mce, IRType ty, IRAtom* addr )
                     VG_(skin_panic)("memcheck:do_shadow_LDle");
    }
 
+   /* Generate the actual address into addrAct. */
+   if (bias == 0) {
+      addrAct = addr;
+   } else {
+      IRType  tyAddr  = mce->hWordTy;
+      sk_assert( tyAddr == Ity_I32 || tyAddr == Ity_I64 );
+      IROp    mkAdd   = tyAddr==Ity_I32 ? Iop_Add32 : Iop_Add64;
+      IRAtom* eBias   = tyAddr==Ity_I32 ? mkU32(bias) : mkU64(bias);
+      addrAct = assignNew(mce, tyAddr, binop(mkAdd, addr, eBias) );
+   }
+
    /* We need to have a place to park the V bits we're just about to
       read. */
    datavbits = newIRTemp(mce->bb->tyenv, ty);
    di = unsafeIRDirty_1_N( datavbits, 
-                           1/*regparms*/, hname, helper, mkIRExprVec_1( addr ));
+                           1/*regparms*/, hname, helper, 
+                           mkIRExprVec_1( addrAct ));
    setHelperAnns( mce, di );
    stmt( mce->bb, IRStmt_Dirty(di) );
 
@@ -1146,7 +1160,8 @@ IRExpr* expr2vbits ( MCEnv* mce, IRExpr* e )
          return expr2vbits_Unop( mce, e->Iex.Unop.op, e->Iex.Unop.arg );
 
       case Iex_LDle:
-         return expr2vbits_LDle( mce, e->Iex.LDle.ty, e->Iex.LDle.addr );
+         return expr2vbits_LDle( mce, e->Iex.LDle.ty, 
+                                      e->Iex.LDle.addr, 0/*addr bias*/ );
 
       case Iex_CCall:
          return mkLazyN( mce, e->Iex.CCall.args, 
@@ -1196,27 +1211,41 @@ IRExpr* zwidenToHostWord ( MCEnv* mce, IRAtom* vatom )
 }
 
 
+/* Generate a shadow store.  addr is always the original address atom.
+   You can pass in either originals or V-bits for the data atom, but
+   obviously not both.  */
+
 static 
-void do_shadow_STle ( MCEnv* mce, IRAtom* addr, IRAtom* data )
+void do_shadow_STle ( MCEnv* mce, 
+                      IRAtom* addr, UInt bias,
+                      IRAtom* data, IRAtom* vdata )
 {
    IRType   ty;
    IRDirty* di;
-   IRExpr*  datavbits;
    void*    helper = NULL;
    Char*    hname = NULL;
+   IRAtom*  addrAct;
 
-   ty = shadowType(typeOfIRExpr(mce->bb->tyenv, data));
+   if (data) {
+      sk_assert(!vdata);
+      sk_assert(isOriginalAtom(mce, data));
+      sk_assert(bias == 0);
+      vdata = expr2vbits( mce, data );
+   } else {
+      sk_assert(vdata);
+   }
 
    sk_assert(isOriginalAtom(mce,addr));
-   sk_assert(isOriginalAtom(mce,data));
+   sk_assert(isShadowAtom(mce,vdata));
+
+   ty = typeOfIRExpr(mce->bb->tyenv, vdata);
 
    /* First, emit a definedness test for the address.  This also sets
       the address (shadow) to 'defined' following the test. */
-   complainIfUndefined( mce, addr);
+   complainIfUndefined( mce, addr );
 
    /* Now cook up a call to the relevant helper function, to write the
       data V bits into shadow memory. */
-   datavbits = expr2vbits( mce, data );
    switch (ty) {
       case Ity_I64: helper = &MC_(helperc_STOREV8);
                     hname = "MC_(helperc_STOREV8)";
@@ -1233,18 +1262,29 @@ void do_shadow_STle ( MCEnv* mce, IRAtom* addr, IRAtom* data )
       default:      VG_(skin_panic)("memcheck:do_shadow_STle");
    }
 
+   /* Generate the actual address into addrAct. */
+   if (bias == 0) {
+      addrAct = addr;
+   } else {
+      IRType  tyAddr  = mce->hWordTy;
+      sk_assert( tyAddr == Ity_I32 || tyAddr == Ity_I64 );
+      IROp    mkAdd   = tyAddr==Ity_I32 ? Iop_Add32 : Iop_Add64;
+      IRAtom* eBias   = tyAddr==Ity_I32 ? mkU32(bias) : mkU64(bias);
+      addrAct = assignNew(mce, tyAddr, binop(mkAdd, addr, eBias) );
+   }
+
    if (ty == Ity_I64) {
       /* We can't do this with regparm 2 on 32-bit platforms, since
          the back ends aren't clever enough to handle 64-bit regparm
          args.  Therefore be different. */
       di = unsafeIRDirty_0_N( 
               1/*regparms*/, hname, helper, 
-              mkIRExprVec_2( addr, datavbits ));
+              mkIRExprVec_2( addrAct, vdata ));
    } else {
       di = unsafeIRDirty_0_N( 
               2/*regparms*/, hname, helper, 
-              mkIRExprVec_2( addr,
-                             zwidenToHostWord( mce, datavbits )));
+              mkIRExprVec_2( addrAct,
+                             zwidenToHostWord( mce, vdata )));
    }
    setHelperAnns( mce, di );
    stmt( mce->bb, IRStmt_Dirty(di) );
@@ -1269,11 +1309,10 @@ static IRType szToITy ( Int n )
 static
 void do_shadow_Dirty ( MCEnv* mce, IRDirty* d )
 {
-   Int    i, offset, toDo;
-   IRAtom *two, *four, *addr, *src;
-   IROp   opAdd;
-   IRType tyAddr, tySrc, tyDst;
-   IRTemp dst;
+   Int     i, offset, toDo;
+   IRAtom* src;
+   IRType  tyAddr, tySrc, tyDst;
+   IRTemp  dst;
 
    /* First check the guard. */
    complainIfUndefined(mce, d->guard);
@@ -1308,8 +1347,6 @@ void do_shadow_Dirty ( MCEnv* mce, IRDirty* d )
 
    /* Inputs: memory.  First set up some info needed regardless of
       whether we're doing reads or writes. */
-   four   = two = NULL;
-   opAdd  = Iop_INVALID;
    tyAddr = Ity_INVALID;
 
    if (d->mFx != Ifx_None) {
@@ -1322,36 +1359,31 @@ void do_shadow_Dirty ( MCEnv* mce, IRDirty* d )
 
       tyAddr = typeOfIRExpr(mce->bb->tyenv, d->mAddr);
       sk_assert(tyAddr == Ity_I32 || tyAddr == Ity_I64);
-      opAdd = tyAddr==Ity_I32 ? Iop_Add32 : Iop_Add64;
-      four  = tyAddr==Ity_I32 ? mkU32(4) : mkU64(4);
-      two   = tyAddr==Ity_I32 ? mkU32(2) : mkU64(2);
+      sk_assert(tyAddr == mce->hWordTy); /* not really right */
    }
 
    /* Deal with memory inputs (reads or modifies) */
    if (d->mFx == Ifx_Read || d->mFx == Ifx_Modify) {
       offset = 0;
       toDo   = d->mSize;
-      addr   = d->mAddr;
       /* chew off 32-bit chunks */
       while (toDo >= 4) {
          here = mkPCastTo( 
                    mce, Ity_I32,
-                   expr2vbits_LDle ( mce, Ity_I32, addr )
+                   expr2vbits_LDle ( mce, Ity_I32, 
+                                     d->mAddr, d->mSize - toDo )
                 );
          curr = mkUifU32(mce, here, curr);
-         addr = assignNew(mce, tyAddr,
-                               binop(opAdd, addr, four));
          toDo -= 4;
       }
       /* chew off 16-bit chunks */
       while (toDo >= 2) {
          here = mkPCastTo( 
                    mce, Ity_I32,
-                   expr2vbits_LDle ( mce, Ity_I16, addr )
+                   expr2vbits_LDle ( mce, Ity_I16, 
+                                     d->mAddr, d->mSize - toDo )
                 );
          curr = mkUifU32(mce, here, curr);
-         addr = assignNew(mce, tyAddr,
-                               binop(opAdd, addr, two));
          toDo -= 2;
       }
       sk_assert(toDo == 0); /* also need to handle 1-byte excess */
@@ -1385,21 +1417,18 @@ void do_shadow_Dirty ( MCEnv* mce, IRDirty* d )
    if (d->mFx == Ifx_Write || d->mFx == Ifx_Modify) {
       offset = 0;
       toDo   = d->mSize;
-      addr   = d->mAddr;
       /* chew off 32-bit chunks */
       while (toDo >= 4) {
-         do_shadow_STle( mce, addr, 
+         do_shadow_STle( mce, d->mAddr, d->mSize - toDo,
+                         NULL, /* original data */
                          mkPCastTo( mce, Ity_I32, curr ) );
-         addr = assignNew(mce, tyAddr,
-                               binop(opAdd, addr, four));
          toDo -= 4;
       }
       /* chew off 16-bit chunks */
       while (toDo >= 2) {
-         do_shadow_STle( mce, addr, 
-                         mkPCastTo( mce, Ity_I32, curr ) );
-         addr = assignNew(mce, tyAddr,
-                               binop(opAdd, addr, two));
+         do_shadow_STle( mce, d->mAddr, d->mSize - toDo,
+                         NULL, /* original data */
+                         mkPCastTo( mce, Ity_I16, curr ) );
          toDo -= 2;
       }
       sk_assert(toDo == 0); /* also need to handle 1-byte excess */
@@ -1556,7 +1585,9 @@ IRBB* SK_(instrument) ( IRBB* bb_in, VexGuestLayout* layout, IRType hWordTy )
             break;
 
          case Ist_STle:
-            do_shadow_STle( &mce, st->Ist.STle.addr, st->Ist.STle.data );
+            do_shadow_STle( &mce, st->Ist.STle.addr, 0/* addr bias */,
+                                  st->Ist.STle.data,
+                                  NULL /* shadow data */ );
             break;
 
          case Ist_Exit: