From: Julian Seward Date: Wed, 3 Nov 2004 15:22:25 +0000 (+0000) Subject: Fix many more cases. X-Git-Tag: svn/VALGRIND_3_0_1^2~853 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=9396ff3f75ffaa1f077db6e4cad979bcc5f71266;p=thirdparty%2Fvalgrind.git Fix many more cases. git-svn-id: svn://svn.valgrind.org/vex/trunk@481 --- diff --git a/VEX/head20041019/memcheck/mc_translate.c b/VEX/head20041019/memcheck/mc_translate.c index abd0962a64..6af206e547 100644 --- a/VEX/head20041019/memcheck/mc_translate.c +++ b/VEX/head20041019/memcheck/mc_translate.c @@ -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;