.offset_SP = offsetof(VexGuestX86State,guest_ESP),
.sizeof_SP = 4,
- /* Describe any indexable sections */
- .n_descrs = 2,
- .descrs[0] = { offsetof(VexGuestX86State,guest_FPREG), Ity_F64, 8 },
- .descrs[1] = { offsetof(VexGuestX86State,guest_FPTAG), Ity_I8, 8 },
+ /* Describe the instruction pointer. */
+ .offset_IP = offsetof(VexGuestX86State,guest_EIP),
+ .sizeof_IP = 4,
/* Describe any sections to be regarded by Memcheck as
'always-defined'. */
}
+/*---------------------------------------------------------------*/
+/*--- Sanity checking -- FLATNESS ---*/
+/*---------------------------------------------------------------*/
+
+/* Check that the canonical flatness constraints hold on an
+ IRStmt. The only place where any expression is allowed to be
+ non-atomic is the RHS of IRStmt_Tmp. */
+
+/* Relies on:
+ inline static Bool isAtom ( IRExpr* e ) {
+ return e->tag == Iex_Tmp || e->tag == Iex_Const;
+ }
+*/
+
+Bool isFlatIRStmt ( IRStmt* st )
+{
+ Int i;
+ IRExpr* e;
+ IRDirty* di;
+
+ switch (st->tag) {
+ case Ist_Put:
+ return isAtom(st->Ist.Put.data);
+ case Ist_PutI:
+ return isAtom(st->Ist.PutI.ix) && isAtom(st->Ist.PutI.data);
+ case Ist_Tmp:
+ /* This is the only interesting case. The RHS can be any
+ expression, *but* all its subexpressions *must* be
+ atoms. */
+ e = st->Ist.Tmp.data;
+ switch (e->tag) {
+ case Iex_Binder: return True;
+ case Iex_Get: return True;
+ case Iex_GetI: return isAtom(e->Iex.GetI.ix);
+ case Iex_Tmp: return True;
+ case Iex_Binop: return isAtom(e->Iex.Binop.arg1)
+ && isAtom(e->Iex.Binop.arg2);
+ case Iex_Unop: return isAtom(e->Iex.Unop.arg);
+ case Iex_LDle: return isAtom(e->Iex.LDle.addr);
+ case Iex_Const: return True;
+ case Iex_CCall: for (i = 0; e->Iex.CCall.args[i]; i++)
+ if (!isAtom(e->Iex.CCall.args[i]))
+ return False;
+ return True;
+ case Iex_Mux0X: return isAtom(e->Iex.Mux0X.cond)
+ && isAtom(e->Iex.Mux0X.expr0)
+ && isAtom(e->Iex.Mux0X.exprX);
+ default: vpanic("isFlatIRStmt(e)");
+ }
+ /*notreached*/
+ vassert(0);
+ case Ist_STle:
+ return isAtom(st->Ist.STle.addr) && isAtom(st->Ist.STle.data);
+ case Ist_Dirty:
+ di = st->Ist.Dirty.details;
+ if (!isAtom(di->guard))
+ return False;
+ for (i = 0; di->args[i]; i++)
+ if (!isAtom(di->args[i]))
+ return False;
+ if (di->mAddr && !isAtom(di->mAddr))
+ return False;
+ return True;
+ case Ist_Exit:
+ return isAtom(st->Ist.Exit.cond);
+ default:
+ vpanic("isFlatIRStmt(st)");
+ }
+}
+
+
/*---------------------------------------------------------------*/
/*--- Sanity checking ---*/
/*---------------------------------------------------------------*/
case Iex_CCall:
if (!saneIRCallee(expr->Iex.CCall.cee))
sanityCheckFail(bb,stmt,"Iex.CCall.cee: bad IRCallee");
- if (expr->Iex.CCall.cee->regparms > countArgs(expr->Iex.CCall.args))
+ if (expr->Iex.CCall.cee->regparms > countArgs(expr->Iex.CCall.args))
sanityCheckFail(bb,stmt,"Iex.CCall.cee: #regparms > #args");
for (i = 0; expr->Iex.CCall.args[i]; i++)
tcExpr(bb,stmt, expr->Iex.CCall.args[i], gWordTy);
d = stmt->Ist.Dirty.details;
if (d->cee == NULL) goto bad_dirty;
if (!saneIRCallee(d->cee)) goto bad_dirty;
- if (d->cee->regparms > countArgs(d->args)) goto bad_dirty;
+ if (d->cee->regparms > countArgs(d->args)) goto bad_dirty;
if (d->mFx == Ifx_None) {
if (d->mAddr != NULL || d->mSize != 0)
goto bad_dirty;
def_counts[stmt->Ist.Tmp.tmp]++;
if (def_counts[stmt->Ist.Tmp.tmp] > 1)
sanityCheckFail(bb, stmt,
- "IRStmt.Tmp: destinatiion tmp is assigned more than once");
+ "IRStmt.Tmp: destination tmp is assigned more than once");
}
else
if (stmt->tag == Ist_Dirty
/* OUT: how much of the output area is used. */
Int* host_bytes_used,
/* IN: optionally, two instrumentation functions. */
- IRBB* (*instrument1) ( IRBB*, VexGuestLayout* ),
- IRBB* (*instrument2) ( IRBB*, VexGuestLayout* ),
+ IRBB* (*instrument1) ( IRBB*, VexGuestLayout*, IRType hWordTy ),
+ IRBB* (*instrument2) ( IRBB*, VexGuestLayout*, IRType hWordTy ),
/* IN: optionally, an access check function for guest code. */
Bool (*byte_accessible) ( Addr64 ),
/* IN: debug: trace vex activity at various points */
HInstrArray* rcode;
Int i, j, k, out_used, guest_sizeB;
UChar insn_bytes[32];
- IRType guest_word_size;
+ IRType guest_word_type;
+ IRType host_word_type;
guest_layout = NULL;
available_real_regs = NULL;
emit = NULL;
specHelper = NULL;
preciseMemExnsFn = NULL;
- guest_word_size = Ity_INVALID;
+ guest_word_type = Ity_INVALID;
+ host_word_type = Ity_INVALID;
vex_traceflags = traceflags;
iselBB = iselBB_X86;
emit = (Int(*)(UChar*,Int,HInstr*)) emit_X86Instr;
host_is_bigendian = False;
+ host_word_type = Ity_I32;
break;
default:
vpanic("LibVEX_Translate: unsupported target insn set");
bbToIR = bbToIR_X86Instr;
specHelper = x86guest_spechelper;
guest_sizeB = sizeof(VexGuestX86State);
- guest_word_size = Ity_I32;
+ guest_word_type = Ity_I32;
guest_layout = &x86guest_layout;
break;
default:
}
/* Sanity check the initial IR. */
- sanityCheckIRBB(irbb, guest_word_size);
+ sanityCheckIRBB(irbb, guest_word_type);
/* Clean it up, hopefully a lot. */
irbb = do_iropt_BB ( irbb, specHelper, preciseMemExnsFn,
guest_bytes_addr );
- sanityCheckIRBB(irbb, guest_word_size);
+ sanityCheckIRBB(irbb, guest_word_type);
if (vex_traceflags & VEX_TRACE_OPT1) {
vex_printf("\n------------------------"
/* Get the thing instrumented. */
if (instrument1)
- irbb = (*instrument1)(irbb, guest_layout);
+ irbb = (*instrument1)(irbb, guest_layout, host_word_type);
if (instrument2)
- irbb = (*instrument2)(irbb, guest_layout);
+ irbb = (*instrument2)(irbb, guest_layout, host_word_type);
if (vex_traceflags & VEX_TRACE_INST) {
vex_printf("\n------------------------"
}
if (instrument1 || instrument2)
- sanityCheckIRBB(irbb, guest_word_size);
+ sanityCheckIRBB(irbb, guest_word_type);
/* Turn it into virtual-registerised code. */
do_deadcode_BB( irbb );
typedef
struct {
- /* Total size of the guest state, in bytes. */
+ /* Total size of the guest state, in bytes. Must be
+ 8-aligned. */
Int total_sizeB;
/* Whereabouts is the stack pointer? */
Int offset_SP;
Int sizeof_SP; /* 4 or 8 */
- /* Describe the indexed sections */
- Int n_descrs; /* must be 0 .. VEXG_N_DESCRS */
- IRArray descrs[VEXGLO_N_DESCRS];
+ /* Whereabouts is the instruction pointer? */
+ Int offset_IP;
+ Int sizeof_IP; /* 4 or 8 */
/* Describe parts of the guest state regarded as 'always
defined'. */
Int n_alwaysDefd;
/* OUT: how much of the output area is used. */
Int* host_bytes_used,
/* IN: optionally, two instrumentation functions. */
- IRBB* (*instrument1) ( IRBB*, VexGuestLayout* ),
- IRBB* (*instrument2) ( IRBB*, VexGuestLayout* ),
+ IRBB* (*instrument1) ( IRBB*, VexGuestLayout*, IRType hWordTy ),
+ IRBB* (*instrument2) ( IRBB*, VexGuestLayout*, IRType hWordTy ),
/* IN: optionally, an access check function for guest code. */
Bool (*byte_accessible) ( Addr64 ),
/* IN: debug: trace vex activity at various points */
Iop_32to1, /* :: Ity_I32 -> Ity_Bit, just select bit[0] */
Iop_1Uto8, /* :: Ity_Bit -> Ity_I8, unsigned widen */
Iop_1Uto32, /* :: Ity_Bit -> Ity_I32, unsigned widen */
+ Iop_1Sto32, /* :: Ity_Bit -> Ity_I32, signed widen */
/* ------ Floating point. We try and be IEEE754 compliant. ------ */
/* Sanity check a BB of IR */
extern void sanityCheckIRBB ( IRBB* bb, IRType guest_word_size );
+extern Bool isFlatIRStmt ( IRStmt* );
/* Is this any value actually in the enumeration 'IRType' ? */
extern Bool isPlausibleType ( IRType ty );