Index: memcheck/mc_translate.c =================================================================== --- memcheck/mc_translate.c (revision 12749) +++ memcheck/mc_translate.c (working copy) @@ -5762,6 +5762,23 @@ } } +static IRAtom* gen_guarded_load_b ( MCEnv* mce, Int szB, IRAtom* baseaddr, + Int offset, IRAtom* guard ) +{ + if (guard) { + IRAtom *cond, *iffalse, *iftrue; + + cond = assignNew('B', mce, Ity_I8, unop(Iop_1Uto8, guard)); + iftrue = assignNew('B', mce, Ity_I32, + gen_load_b(mce, szB, baseaddr, offset)); + iffalse = mkU32(0); + + return assignNew('B', mce, Ity_I32, IRExpr_Mux0X(cond, iffalse, iftrue)); + } + + return gen_load_b(mce, szB, baseaddr, offset); +} + /* Generate a shadow store. guard :: Ity_I1 controls whether the store really happens; NULL means it unconditionally does. */ static void gen_store_b ( MCEnv* mce, Int szB, @@ -5984,7 +6001,8 @@ /* Now round up all inputs and maxU32 over them. */ - /* Inputs: unmasked args */ + /* Inputs: unmasked args + Note: arguments are evaluated REGARDLESS of the guard expression */ for (i = 0; d->args[i]; i++) { if (d->cee->mcx_mask & (1<layout->total_sizeB, - Ity_I32)); + /* Observe the guard expression. If it is false use 0, i.e. + nothing is known about the origin */ + IRAtom *cond, *iffalse, *iftrue; + + cond = assignNew( 'B', mce, Ity_I8, unop(Iop_1Uto8, d->guard)); + iffalse = mkU32(0); + iftrue = assignNew( 'B', mce, Ity_I32, + IRExpr_Get(b_offset + + 2*mce->layout->total_sizeB, + Ity_I32)); + here = assignNew( 'B', mce, Ity_I32, + IRExpr_Mux0X(cond, iffalse, iftrue)); curr = gen_maxU32( mce, curr, here ); } gSz -= n; @@ -6058,19 +6083,22 @@ but nevertheless choose an endianness which is hopefully native to the platform. */ while (toDo >= 4) { - here = gen_load_b( mce, 4, d->mAddr, d->mSize - toDo ); + here = gen_guarded_load_b( mce, 4, d->mAddr, d->mSize - toDo, + d->guard ); curr = gen_maxU32( mce, curr, here ); toDo -= 4; } /* handle possible 16-bit excess */ while (toDo >= 2) { - here = gen_load_b( mce, 2, d->mAddr, d->mSize - toDo ); + here = gen_guarded_load_b( mce, 2, d->mAddr, d->mSize - toDo, + d->guard ); curr = gen_maxU32( mce, curr, here ); toDo -= 2; } /* chew off the remaining 8-bit chunk, if any */ if (toDo == 1) { - here = gen_load_b( mce, 1, d->mAddr, d->mSize - toDo ); + here = gen_guarded_load_b( mce, 1, d->mAddr, d->mSize - toDo, + d->guard ); curr = gen_maxU32( mce, curr, here ); toDo -= 1; } @@ -6113,6 +6141,20 @@ /* Write 'curr' to the state slice gOff .. gOff+n-1 */ b_offset = MC_(get_otrack_shadow_offset)(gOff, 4); if (b_offset != -1) { + if (d->guard) { + /* If the guard expression evaluates to false we simply Put + the value that is already stored in the guest state slot */ + IRAtom *cond, *iffalse; + + cond = assignNew('B', mce, Ity_I8, + unop(Iop_1Uto8, d->guard)); + iffalse = assignNew('B', mce, Ity_I32, + IRExpr_Get(b_offset + + 2*mce->layout->total_sizeB, + Ity_I32)); + curr = assignNew('V', mce, Ity_I32, + IRExpr_Mux0X(cond, iffalse, curr)); + } stmt( 'B', mce, IRStmt_Put(b_offset + 2*mce->layout->total_sizeB, curr )); @@ -6130,19 +6172,19 @@ /* chew off 32-bit chunks */ while (toDo >= 4) { gen_store_b( mce, 4, d->mAddr, d->mSize - toDo, curr, - NULL/*guard*/ ); + d->guard ); toDo -= 4; } /* handle possible 16-bit excess */ while (toDo >= 2) { gen_store_b( mce, 2, d->mAddr, d->mSize - toDo, curr, - NULL/*guard*/ ); + d->guard ); toDo -= 2; } /* chew off the remaining 8-bit chunk, if any */ if (toDo == 1) { gen_store_b( mce, 1, d->mAddr, d->mSize - toDo, curr, - NULL/*guard*/ ); + d->guard ); toDo -= 1; } tl_assert(toDo == 0);