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");
}
}
#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))
/* 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));
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 ) {
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. */
return assignNew(mce, Ity_I32, unop(Iop_1Sto32, tmp1));
default:
ppIRType(dst_ty);
- VG_(skin_panic)("genPCastTo(2)");
+ VG_(skin_panic)("mkPCastTo(2)");
}
}
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));
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 ) );
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));
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");
}
+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 )
{
/* 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. */
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,
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 );
/* 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. */
case Ist_Put:
do_shadow_PUT( &mce,
st->Ist.Put.offset,
- expr2vbits( &mce, st->Ist.Put.data),
st->Ist.Put.data );
break;
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);
/* 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;