]> git.ipfire.org Git - thirdparty/valgrind.git/commitdiff
Fix many more cases.
authorJulian Seward <jseward@acm.org>
Wed, 3 Nov 2004 15:22:25 +0000 (15:22 +0000)
committerJulian Seward <jseward@acm.org>
Wed, 3 Nov 2004 15:22:25 +0000 (15:22 +0000)
git-svn-id: svn://svn.valgrind.org/vex/trunk@481

VEX/head20041019/memcheck/mc_translate.c

index abd0962a646e697a971ea864f083b71c3dd3f1d2..6af206e547bf542b4d45ccee2d5f3892def653d4 100644 (file)
@@ -1716,8 +1716,12 @@ static Bool isShadowAtom ( MCEnv* mce, IRAtom* a1 )
 static IRType shadowType ( IRType ty )
 {
    switch (ty) {
+      case Ity_Bit:
+      case Ity_I8:
+      case Ity_I16:
       case Ity_I32: return ty;
-      default: VG_(skin_panic)("memcheck:shadowType");
+      default: ppIRType(ty); 
+               VG_(skin_panic)("memcheck:shadowType");
    }
 }
 
@@ -1759,6 +1763,8 @@ static IRExpr* expr2vbits ( MCEnv* mce, IRExpr* e );
 
 #define binop(_op, _arg1, _arg2) IRExpr_Binop((_op),(_arg1),(_arg2))
 #define unop(_op, _arg)          IRExpr_Unop((_op),(_arg))
+#define mkU8(_n)                 IRExpr_Const(IRConst_U8(_n))
+#define mkU16(_n)                IRExpr_Const(IRConst_U16(_n))
 #define mkU32(_n)                IRExpr_Const(IRConst_U32(_n))
 #define mkU64(_n)                IRExpr_Const(IRConst_U64(_n))
 #define mkexpr(_tmp)             IRExpr_Tmp((_tmp))
@@ -1772,11 +1778,19 @@ static IRAtom* assignNew ( MCEnv* mce, IRType ty, IRExpr* e ) {
 /* Should only be supplied shadow types (I8/I16/I32/UI64). */
 static IRExpr* definedOfType ( IRType ty ) {
    switch (ty) {
+      case Ity_Bit: return IRExpr_Const(IRConst_Bit(False));
+      case Ity_I8:  return mkU8(0);
       case Ity_I32: return mkU32(0);
       default:      VG_(skin_panic)("memcheck:definedOfType");
    }
 }
 
+static IRAtom* mkUifU16 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
+   sk_assert(isShadowAtom(mce,a1));
+   sk_assert(isShadowAtom(mce,a2));
+   return assignNew(mce, Ity_I16, binop(Iop_Or16, a1, a2));
+}
+
 static IRAtom* mkUifU32 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
    sk_assert(isShadowAtom(mce,a1));
    sk_assert(isShadowAtom(mce,a2));
@@ -1787,7 +1801,10 @@ static IRExpr* mkLeft32 ( MCEnv* mce, IRAtom* a1 ) {
    sk_assert(isShadowAtom(mce,a1));
    /* It's safe to duplicate a1 since it's only an atom */
    return assignNew(mce, Ity_I32, 
-                         binop(Iop_Or32, a1, unop(Iop_Neg32, a1)));
+             binop(Iop_Or32, a1, 
+                   assignNew(mce, Ity_I32,
+                   /* unop(Iop_Neg32, a1)))); */
+                   binop(Iop_Sub32, mkU32(0), a1) )));
 }
 
 static void setHelperAnns ( MCEnv* mce, IRDirty* di ) {
@@ -1800,17 +1817,27 @@ static void setHelperAnns ( MCEnv* mce, IRDirty* di ) {
    di->fxState[1].size   = mce->layout->sizeof_IP;
 }
 
-static IRAtom* genPCastTo( MCEnv* mce, IRAtom* vbits, IRType dst_ty ) {
+/* Note, dst_ty is a V-bits type, not an original type. */
+static IRAtom* mkPCastTo( MCEnv* mce, IRAtom* vbits, IRType dst_ty ) {
    /* First of all, collapse vbits down to a single bit. */
    sk_assert(isShadowAtom(mce,vbits));
    IRType  ty   = typeOfIRExpr(mce->bb->tyenv, vbits);
    IRAtom* tmp1 = NULL;
    switch (ty) {
+      case Ity_Bit:
+         tmp1 = vbits;
+         break;
+      case Ity_I8: 
+         tmp1 = assignNew(mce, Ity_Bit, binop(Iop_CmpNE8, vbits, mkU8(0)));
+         break;
+      case Ity_I16: 
+         tmp1 = assignNew(mce, Ity_Bit, binop(Iop_CmpNE16, vbits, mkU16(0)));
+         break;
       case Ity_I32: 
          tmp1 = assignNew(mce, Ity_Bit, binop(Iop_CmpNE32, vbits, mkU32(0)));
          break;
       default:
-         VG_(skin_panic)("genPCastTo(1)");
+         VG_(skin_panic)("mkPCastTo(1)");
    }
    sk_assert(tmp1);
    /* Now widen up to the dst type. */
@@ -1821,7 +1848,7 @@ static IRAtom* genPCastTo( MCEnv* mce, IRAtom* vbits, IRType dst_ty ) {
          return assignNew(mce, Ity_I32, unop(Iop_1Sto32, tmp1));
       default: 
          ppIRType(dst_ty);
-         VG_(skin_panic)("genPCastTo(2)");
+         VG_(skin_panic)("mkPCastTo(2)");
    }
 }
 
@@ -1856,24 +1883,32 @@ static Bool isAlwaysDefd ( MCEnv* mce, Int offset, Int size )
 
 
 static
-void complainIfUndefined ( MCEnv* mce, IRAtom* vatom, IRAtom* atom )
+void complainIfUndefined ( MCEnv* mce, IRAtom* atom )
 {
-   /* vatom is required to be the V-bits shadow for atom. */
+  //  static Int zzz=100;
+
+   /* Since the original expression is atomic, there's no duplicated
+      work generated by making multiple V-expressions for it.  So we
+      don't really care about the possibility that someone else may
+      also create a V-interpretion for it. */
    sk_assert(isOriginalAtom(mce, atom));
+   IRAtom* vatom = expr2vbits( mce, atom );
    sk_assert(isShadowAtom(mce, vatom));
    sk_assert(sameKindedAtoms(atom, vatom));
 
    IRType ty = typeOfIRExpr(mce->bb->tyenv, vatom);
-   Int    sz = sizeofIRType(ty);
 
-   IRExpr* cond = genPCastTo( mce, vatom, Ity_Bit );
+   /* sz is only used for constructing the error message */
+   Int    sz = ty==Ity_Bit ? 0 : sizeofIRType(ty);
+
+   IRExpr* cond = mkPCastTo( mce, vatom, Ity_Bit );
    /* cond will be 0 if all defined, and 1 if any not defined. */
 
    IRDirty* di 
       = unsafeIRDirty_0_N( 1/*regparms*/, 
                            "MC_(helperc_complain_undef)",
                            &MC_(helperc_complain_undef),
-                           mkIRExprVec_1( mkIRExpr_HWord(sz) ));
+                           mkIRExprVec_1( mkIRExpr_HWord( sz /* zzz++ */ ) ));
    di->guard = cond;
    setHelperAnns( mce, di );
    stmt( mce->bb, IRStmt_Dirty(di));
@@ -1897,17 +1932,18 @@ void complainIfUndefined ( MCEnv* mce, IRAtom* vatom, IRAtom* atom )
    supplied V bits are 1, and do not modify shadow state.  Otherwise,
    write the supplied V bits to the shadow state. */
 static
-void do_shadow_PUT ( MCEnv* mce, Int offset, IRAtom* vatom, IRAtom* atom )
+void do_shadow_PUT ( MCEnv* mce, Int offset, IRAtom* atom )
 {
    /* vatom is required to be the V-bits shadow for atom. */
    sk_assert(isOriginalAtom(mce, atom));
+   IRAtom* vatom = expr2vbits( mce, atom );
    sk_assert(isShadowAtom(mce, vatom));
    sk_assert(sameKindedAtoms(atom, vatom));
    IRType ty = typeOfIRExpr(mce->bb->tyenv, vatom);
    sk_assert(ty != Ity_Bit);
    if (isAlwaysDefd(mce, offset, sizeofIRType(ty))) {
       /* emit code to emit a complaint if any of the vbits are 1. */
-      complainIfUndefined(mce, vatom, atom);
+      complainIfUndefined(mce, atom);
    } else {
       /* Do a plain shadow Put. */
       stmt( mce->bb, IRStmt_Put( offset + mce->layout->total_sizeB, vatom ) );
@@ -1965,7 +2001,6 @@ IRExpr* expr2vbits_Binop ( MCEnv* mce,
                            IRExpr* atom1, IRExpr* atom2,
                            IRExpr* vatom1, IRExpr* vatom2 )
 {
-   IRAtom* ta;
    sk_assert(isOriginalAtom(mce,atom1));
    sk_assert(isOriginalAtom(mce,atom2));
    sk_assert(isShadowAtom(mce,vatom1));
@@ -1975,8 +2010,22 @@ IRExpr* expr2vbits_Binop ( MCEnv* mce,
    switch (op) {
       case Iop_Sub32:
       case Iop_Add32:
-         ta = mkUifU32(mce,vatom1,vatom2);
-         return mkLeft32(mce, ta);
+         return mkLeft32(mce, mkUifU32(mce, vatom1,vatom2));
+
+      case Iop_CmpLE32S: case Iop_CmpLE32U: case Iop_CmpLT32U:
+      case Iop_CmpEQ32:
+         return mkPCastTo(mce, mkUifU32(mce, vatom1,vatom2), Ity_Bit);
+
+      case Iop_CmpEQ16:
+         return mkPCastTo(mce, mkUifU16(mce, vatom1,vatom2), Ity_Bit);
+
+      case Iop_Shl32:
+      case Iop_Shr32:
+         /* Complain if the shift amount is undefined.  Then simply
+            shift the first arg's V bits by the real shift amount. */
+         complainIfUndefined(mce, atom2);
+         return assignNew(mce, Ity_I32, binop(op, vatom1, atom2));
+
       default:
          ppIROp(op);
          VG_(skin_panic)("memcheck:expr2vbits_Binop");
@@ -1984,6 +2033,32 @@ IRExpr* expr2vbits_Binop ( MCEnv* mce,
 }
 
 
+static 
+IRExpr* expr2vbits_Unop ( MCEnv* mce,
+                          IROp op,
+                          IRExpr* atom, IRExpr* vatom )
+{
+   sk_assert(isOriginalAtom(mce,atom));
+   sk_assert(isShadowAtom(mce,vatom));
+   sk_assert(sameKindedAtoms(atom,vatom));
+   switch (op) {
+      case Iop_1Uto32:
+      case Iop_8Uto32:
+      case Iop_16Uto32:
+         return assignNew(mce, Ity_I32, unop(op, vatom));
+      case Iop_32to1:
+         return assignNew(mce, Ity_Bit, unop(Iop_32to1, vatom));
+      case Iop_32to16:
+         return assignNew(mce, Ity_I16, unop(Iop_32to16, vatom));
+      case Iop_Not1:
+         return vatom;
+      default:
+         ppIROp(op);
+         VG_(skin_panic)("memcheck:expr2vbits_Unop");
+   }
+}
+
+
 static
 IRExpr* expr2vbits_LDle ( MCEnv* mce, IRType ty, IRAtom* addr )
 {
@@ -1996,7 +2071,7 @@ IRExpr* expr2vbits_LDle ( MCEnv* mce, IRType ty, IRAtom* addr )
 
    /* First, emit a definedness test for the address.  This also sets
       the address (shadow) to 'defined' following the test. */
-   complainIfUndefined( mce, expr2vbits( mce, addr ), addr );
+   complainIfUndefined( mce, addr );
 
    /* Now cook up a call to the relevant helper function, to read the
       data V bits from shadow memory. */
@@ -2041,8 +2116,8 @@ IRExpr* expr2vbits ( MCEnv* mce, IRExpr* e )
          return definedOfType(shadowType(typeOfIRExpr(mce->bb->tyenv, e)));
 
       case Iex_Binop:
-         v1 = expr2vbits( mce, e->Iex.Binop.arg1);
-         v2 = expr2vbits( mce, e->Iex.Binop.arg2);
+         v1 = expr2vbits( mce, e->Iex.Binop.arg1 );
+         v2 = expr2vbits( mce, e->Iex.Binop.arg2 );
          return expr2vbits_Binop(
                    mce,
                    e->Iex.Binop.op,
@@ -2050,6 +2125,14 @@ IRExpr* expr2vbits ( MCEnv* mce, IRExpr* e )
                    v1, v2 
                 );
 
+      case Iex_Unop:
+         v1 = expr2vbits( mce, e->Iex.Unop.arg );
+         return expr2vbits_Unop(
+                   mce,
+                   e->Iex.Unop.op,
+                   e->Iex.Unop.arg, v1
+                );
+
       case Iex_LDle:
          return expr2vbits_LDle( mce, e->Iex.LDle.ty, e->Iex.LDle.addr );
 
@@ -2094,7 +2177,7 @@ void do_shadow_STle ( MCEnv* mce, IRAtom* addr, IRAtom* data )
 
    /* First, emit a definedness test for the address.  This also sets
       the address (shadow) to 'defined' following the test. */
-   complainIfUndefined( mce, expr2vbits( mce, addr ), addr);
+   complainIfUndefined( mce, addr);
 
    /* Now cook up a call to the relevant helper function, to write the
       data V bits into shadow memory. */
@@ -2177,7 +2260,6 @@ IRBB* SK_(instrument) ( IRBB* bb_in, VexGuestLayout* layout, IRType hWordTy )
          case Ist_Put:
             do_shadow_PUT( &mce, 
                            st->Ist.Put.offset,
-                           expr2vbits( &mce, st->Ist.Put.data),
                            st->Ist.Put.data );
             break;
 
@@ -2185,6 +2267,10 @@ IRBB* SK_(instrument) ( IRBB* bb_in, VexGuestLayout* layout, IRType hWordTy )
             do_shadow_STle( &mce, st->Ist.STle.addr, st->Ist.STle.data );
             break;
 
+         case Ist_Exit:
+            complainIfUndefined( &mce, st->Ist.Exit.cond );
+            break;
+
          default:
             VG_(printf)("\n");
             ppIRStmt(st);
@@ -2208,7 +2294,24 @@ IRBB* SK_(instrument) ( IRBB* bb_in, VexGuestLayout* layout, IRType hWordTy )
 
    /* Uh, ok.  Now we need to complain if the jump target is
       undefined. */
-   complainIfUndefined( &mce, expr2vbits( &mce, bb->next ), bb->next );
+   first_stmt = bb->stmts_used;
+
+   if (verbose) {
+      VG_(printf)("bb->next = ");
+      ppIRExpr(bb->next);
+      VG_(printf)("\n\n");
+   }
+
+   complainIfUndefined( &mce, bb->next );
+
+   if (verbose) {
+      for (j = first_stmt; j < bb->stmts_used; j++) {
+         VG_(printf)("   ");
+         ppIRStmt(bb->stmts[j]);
+         VG_(printf)("\n");
+      }
+      VG_(printf)("\n");
+   }
 
    return bb;