Start adding floating point stuff to memcheck.

git-svn-id: svn://svn.valgrind.org/vex/trunk@495
This commit is contained in:
Julian Seward
2004-11-05 01:56:14 +00:00
parent eb9bd3ab50
commit 5cbf58bb7a
2 changed files with 89 additions and 14 deletions

View File

@@ -14,6 +14,7 @@ VALGRIND_2.1 {
*IRTemp*;
*IRConst*;
*IRCallee*;
*IRArray*;
LibVEX_Alloc;
local:

View File

@@ -1721,6 +1721,8 @@ static IRType shadowType ( IRType ty )
case Ity_I16:
case Ity_I32:
case Ity_I64: return ty;
case Ity_F32: return Ity_I32;
case Ity_F64: return Ity_I64;
default: ppIRType(ty);
VG_(skin_panic)("memcheck:shadowType");
}
@@ -1819,9 +1821,16 @@ static IRAtom* mkUifU32 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
sk_assert(isShadowAtom(mce,a2));
return assignNew(mce, Ity_I32, binop(Iop_Or32, a1, a2));
}
static IRAtom* mkUifU64 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
sk_assert(isShadowAtom(mce,a1));
sk_assert(isShadowAtom(mce,a2));
return assignNew(mce, Ity_I64, binop(Iop_Or64, a1, a2));
}
static IRAtom* mkUifU ( MCEnv* mce, IRType vty, IRAtom* a1, IRAtom* a2 ) {
switch (vty) {
case Ity_I32: return mkUifU32(mce, a1, a2);
case Ity_I64: return mkUifU64(mce, a1, a2);
default:
VG_(printf)("\n"); ppIRType(vty); VG_(printf)("\n");
VG_(skin_panic)("memcheck:mkUifU");
@@ -1924,7 +1933,7 @@ static void setHelperAnns ( MCEnv* mce, IRDirty* di ) {
}
/* Note, dst_ty is a V-bits type, not an original type. */
static IRAtom* mkPCastTo( MCEnv* mce, IRAtom* vbits, IRType dst_ty ) {
static IRAtom* mkPCastTo( MCEnv* mce, IRType dst_ty, IRAtom* vbits ) {
/* First of all, collapse vbits down to a single bit. */
sk_assert(isShadowAtom(mce,vbits));
IRType ty = typeOfIRExpr(mce->bb->tyenv, vbits);
@@ -1953,6 +1962,8 @@ static IRAtom* mkPCastTo( MCEnv* mce, IRAtom* vbits, IRType dst_ty ) {
switch (dst_ty) {
case Ity_Bit:
return tmp1;
case Ity_I16:
return assignNew(mce, Ity_I16, unop(Iop_1Sto16, tmp1));
case Ity_I32:
return assignNew(mce, Ity_I32, unop(Iop_1Sto32, tmp1));
case Ity_I64:
@@ -2012,7 +2023,7 @@ void complainIfUndefined ( MCEnv* mce, IRAtom* atom )
/* sz is only used for constructing the error message */
Int sz = ty==Ity_Bit ? 0 : sizeofIRType(ty);
IRAtom* cond = mkPCastTo( mce, vatom, Ity_Bit );
IRAtom* cond = mkPCastTo( mce, Ity_Bit, vatom );
/* cond will be 0 if all defined, and 1 if any not defined. */
IRDirty* di
@@ -2048,10 +2059,10 @@ IRAtom* doLazyApproximation ( MCEnv* mce,
IRAtom* curr = definedOfType(Ity_I32);
for (i = 0; exprvec[i]; i++) {
sk_assert(isOriginalAtom(mce, exprvec[i]));
here = mkPCastTo( mce, expr2vbits(mce, exprvec[i]), Ity_I32 );
here = mkPCastTo( mce, Ity_I32, expr2vbits(mce, exprvec[i]) );
curr = mkUifU32(mce, here, curr);
}
return mkPCastTo(mce, curr, finalVtype );
return mkPCastTo(mce, finalVtype, curr );
}
/* Generate into bb suitable actions to shadow this Put. If the state
@@ -2078,6 +2089,34 @@ void do_shadow_PUT ( MCEnv* mce, Int offset, IRAtom* atom )
}
/* Return an expression which contains the V bits corresponding to the
given GETI (passed in in pieces).
*/
static
void do_shadow_PUTI ( MCEnv* mce, IRArray* descr, IRAtom* ix, Int bias, IRAtom* atom )
{
sk_assert(isOriginalAtom(mce,atom));
IRAtom* vatom = expr2vbits( mce, atom );
sk_assert(sameKindedAtoms(atom, vatom));
IRType ty = descr->elemTy;
IRType tyS = shadowType(ty);
Int arrSize = descr->nElems * sizeofIRType(ty);
sk_assert(ty != Ity_Bit);
sk_assert(isOriginalAtom(mce,ix));
complainIfUndefined(mce,ix);
if (isAlwaysDefd(mce, descr->base, arrSize)) {
/* emit code to emit a complaint if any of the vbits are 1. */
complainIfUndefined(mce, atom);
} else {
/* Do a cloned version of the Put that refers to the shadow
area. */
IRArray* new_descr
= mkIRArray( descr->base + mce->layout->total_sizeB,
tyS, descr->nElems);
stmt( mce->bb, IRStmt_PutI( new_descr, ix, bias, vatom ));
}
}
/* Return an expression which contains the V bits corresponding to the
given GET (passed in in pieces).
*/
@@ -2108,6 +2147,7 @@ IRExpr* shadow_GETI ( MCEnv* mce, IRArray* descr, IRAtom* ix, Int bias )
Int arrSize = descr->nElems * sizeofIRType(ty);
sk_assert(ty != Ity_Bit);
sk_assert(isOriginalAtom(mce,ix));
complainIfUndefined(mce,ix);
if (isAlwaysDefd(mce, descr->base, arrSize)) {
/* Always defined, return all zeroes of the relevant type */
return definedOfType(tyS);
@@ -2123,13 +2163,15 @@ IRExpr* shadow_GETI ( MCEnv* mce, IRArray* descr, IRAtom* ix, Int bias )
static
IRAtom* lazy2 ( MCEnv* mce, IRType finalVty, IRAtom* a1, IRAtom* a2 )
IRAtom* lazy2 ( MCEnv* mce, IRType finalVty, IRAtom* va1, IRAtom* va2 )
{
/* force everything via 32-bit intermediaries. */
IRAtom* at;
at = mkPCastTo(mce, a1, Ity_I32);
at = mkUifU(mce, Ity_I32, at, mkPCastTo(mce, a2, Ity_I32));
at = mkPCastTo(mce, at, finalVty);
sk_assert(isShadowAtom(mce,va1));
sk_assert(isShadowAtom(mce,va2));
at = mkPCastTo(mce, Ity_I32, va1);
at = mkUifU(mce, Ity_I32, at, mkPCastTo(mce, Ity_I32, va2));
at = mkPCastTo(mce, finalVty, at);
return at;
}
@@ -2152,6 +2194,19 @@ IRAtom* expr2vbits_Binop ( MCEnv* mce,
sk_assert(sameKindedAtoms(atom2,vatom2));
switch (op) {
case Iop_F64toI32:
/* First arg is I32 (rounding mode), second is F64 (data). */
return lazy2(mce, Ity_I32, vatom1, vatom2);
case Iop_F64toI16:
/* First arg is I32 (rounding mode), second is F64 (data). */
return lazy2(mce, Ity_I16, vatom1, vatom2);
case Iop_MulF64:
return lazy2(mce, Ity_I64, vatom1, vatom2);
/* non-FP after here */
case Iop_DivModU64to32:
case Iop_DivModS64to32:
return lazy2(mce, Ity_I64, vatom1, vatom2);
@@ -2163,7 +2218,7 @@ IRAtom* expr2vbits_Binop ( MCEnv* mce,
case Iop_MullS32:
case Iop_MullU32: {
IRAtom* vLo32 = mkLeft32(mce, mkUifU32(mce, vatom1,vatom2));
IRAtom* vHi32 = mkPCastTo(mce, vLo32, Ity_I32);
IRAtom* vHi32 = mkPCastTo(mce, Ity_I32, vLo32);
return assignNew(mce, Ity_I64, binop(Iop_32HLto64, vHi32, vLo32));
}
@@ -2182,13 +2237,13 @@ IRAtom* expr2vbits_Binop ( MCEnv* mce,
case Iop_CmpLE32S: case Iop_CmpLE32U:
case Iop_CmpLT32U: case Iop_CmpLT32S:
case Iop_CmpEQ32: case Iop_CmpNE32:
return mkPCastTo(mce, mkUifU32(mce, vatom1,vatom2), Ity_Bit);
return mkPCastTo(mce, Ity_Bit, mkUifU32(mce, vatom1,vatom2));
case Iop_CmpEQ16:
return mkPCastTo(mce, mkUifU16(mce, vatom1,vatom2), Ity_Bit);
return mkPCastTo(mce, Ity_Bit, mkUifU16(mce, vatom1,vatom2));
case Iop_CmpEQ8: case Iop_CmpNE8:
return mkPCastTo(mce, mkUifU8(mce, vatom1,vatom2), Ity_Bit);
return mkPCastTo(mce, Ity_Bit, mkUifU8(mce, vatom1,vatom2));
case Iop_Shl32: case Iop_Shr32: case Iop_Sar32:
/* Complain if the shift amount is undefined. Then simply
@@ -2258,6 +2313,11 @@ IRExpr* expr2vbits_Unop ( MCEnv* mce,
sk_assert(isShadowAtom(mce,vatom));
sk_assert(sameKindedAtoms(atom,vatom));
switch (op) {
case Iop_F32toF64:
case Iop_I32toF64:
return mkPCastTo(mce, Ity_I64, vatom);
case Iop_64to32:
case Iop_64HIto32:
case Iop_1Uto32:
@@ -2304,6 +2364,7 @@ IRAtom* expr2vbits_LDle ( MCEnv* mce, IRType ty, IRAtom* addr )
/* Now cook up a call to the relevant helper function, to read the
data V bits from shadow memory. */
ty = shadowType(ty);
switch (ty) {
case Ity_I32: helper = &MC_(helperc_LOADV4);
hname = "MC_(helperc_LOADV4)";
@@ -2314,7 +2375,8 @@ IRAtom* expr2vbits_LDle ( MCEnv* mce, IRType ty, IRAtom* addr )
case Ity_I8: helper = &MC_(helperc_LOADV1);
hname = "MC_(helperc_LOADV1)";
break;
default: VG_(skin_panic)("memcheck:do_shadow_LDle");
default: ppIRType(ty);
VG_(skin_panic)("memcheck:do_shadow_LDle");
}
/* We need to have a place to park the V bits we're just about to
@@ -2351,7 +2413,7 @@ IRAtom* expr2vbits_Mux0X ( MCEnv* mce,
return
mkUifU(mce, ty, assignNew(mce, ty, IRExpr_Mux0X(cond, vbits0, vbitsX)),
mkPCastTo(mce, vbitsC, ty) );
mkPCastTo(mce, ty, vbitsC) );
}
@@ -2364,6 +2426,10 @@ IRExpr* expr2vbits ( MCEnv* mce, IRExpr* e )
case Iex_Get:
return shadow_GET( mce, e->Iex.Get.offset, e->Iex.Get.ty );
case Iex_GetI:
return shadow_GETI( mce, e->Iex.GetI.descr,
e->Iex.GetI.ix, e->Iex.GetI.bias );
case Iex_Tmp:
return IRExpr_Tmp( findShadowTmp(mce, e->Iex.Tmp.tmp) );
@@ -2532,6 +2598,14 @@ IRBB* SK_(instrument) ( IRBB* bb_in, VexGuestLayout* layout, IRType hWordTy )
st->Ist.Put.data );
break;
case Ist_PutI:
do_shadow_PUTI( &mce,
st->Ist.PutI.descr,
st->Ist.PutI.ix,
st->Ist.PutI.bias,
st->Ist.PutI.data );
break;
case Ist_STle:
do_shadow_STle( &mce, st->Ist.STle.addr, st->Ist.STle.data );
break;