precise memory exceptions. This is logically part of the guest
state description. */
extern
-Bool guest_amd64_state_requires_precise_mem_exns ( Int, Int );
+Bool guest_amd64_state_requires_precise_mem_exns ( Int, Int,
+ VexRegisterUpdates );
extern
VexGuestLayout amd64guest_layout;
Only %RSP is needed in mode VexRegUpdSpAtMemAccess.
*/
-Bool guest_amd64_state_requires_precise_mem_exns ( Int minoff,
- Int maxoff)
+Bool guest_amd64_state_requires_precise_mem_exns (
+ Int minoff, Int maxoff, VexRegisterUpdates pxControl
+ )
{
Int rbp_min = offsetof(VexGuestAMD64State, guest_RBP);
Int rbp_max = rbp_min + 8 - 1;
if (maxoff < rsp_min || minoff > rsp_max) {
/* no overlap with rsp */
- if (vex_control.iropt_register_updates == VexRegUpdSpAtMemAccess)
+ if (pxControl == VexRegUpdSpAtMemAccess)
return False; // We only need to check stack pointer.
} else {
return True;
precise memory exceptions. This is logically part of the guest
state description. */
extern
-Bool guest_arm64_state_requires_precise_mem_exns ( Int, Int );
+Bool guest_arm64_state_requires_precise_mem_exns ( Int, Int,
+ VexRegisterUpdates );
extern
VexGuestLayout arm64Guest_layout;
We enforce precise exns for guest SP, PC, 29(FP), 30(LR).
That might be overkill (for 29 and 30); I don't know.
*/
-Bool guest_arm64_state_requires_precise_mem_exns ( Int minoff,
- Int maxoff)
+Bool guest_arm64_state_requires_precise_mem_exns (
+ Int minoff, Int maxoff, VexRegisterUpdates pxControl
+ )
{
Int xsp_min = offsetof(VexGuestARM64State, guest_XSP);
Int xsp_max = xsp_min + 8 - 1;
if (maxoff < xsp_min || minoff > xsp_max) {
/* no overlap with xsp */
- if (vex_control.iropt_register_updates == VexRegUpdSpAtMemAccess)
+ if (pxControl == VexRegUpdSpAtMemAccess)
return False; // We only need to check stack pointer.
} else {
return True;
precise memory exceptions. This is logically part of the guest
state description. */
extern
-Bool guest_arm_state_requires_precise_mem_exns ( Int, Int );
+Bool guest_arm_state_requires_precise_mem_exns ( Int, Int,
+ VexRegisterUpdates );
extern
VexGuestLayout armGuest_layout;
Only R13(sp) is needed in mode VexRegUpdSpAtMemAccess.
*/
-Bool guest_arm_state_requires_precise_mem_exns ( Int minoff,
- Int maxoff)
+Bool guest_arm_state_requires_precise_mem_exns (
+ Int minoff, Int maxoff, VexRegisterUpdates pxControl
+ )
{
Int sp_min = offsetof(VexGuestARMState, guest_R13);
Int sp_max = sp_min + 4 - 1;
if (maxoff < sp_min || minoff > sp_max) {
/* no overlap with sp */
- if (vex_control.iropt_register_updates == VexRegUpdSpAtMemAccess)
+ if (pxControl == VexRegUpdSpAtMemAccess)
return False; // We only need to check stack pointer.
} else {
return True;
/*OUT*/VexGuestExtents* vge,
/*OUT*/UInt* n_sc_extents,
/*OUT*/UInt* n_guest_instrs, /* stats only */
+ /*MOD*/VexRegisterUpdates* pxControl,
/*IN*/ void* callback_opaque,
/*IN*/ DisOneInstrFn dis_instr_fn,
/*IN*/ const UChar* guest_code,
/*IN*/ const VexArchInfo* archinfo_guest,
/*IN*/ const VexAbiInfo* abiinfo_both,
/*IN*/ IRType guest_word_type,
- /*IN*/ UInt (*needs_self_check)(void*,const VexGuestExtents*),
+ /*IN*/ UInt (*needs_self_check)
+ (void*, /*MB_MOD*/VexRegisterUpdates*,
+ const VexGuestExtents*),
/*IN*/ Bool (*preamble_function)(void*,IRSB*),
/*IN*/ Int offB_GUEST_CMSTART,
/*IN*/ Int offB_GUEST_CMLEN,
IRType host_word_type = Ity_INVALID;
UInt extents_needing_check
- = needs_self_check(callback_opaque, vge);
+ = needs_self_check(callback_opaque, pxControl, vge);
if (host_word_szB == 4) host_word_type = Ity_I32;
if (host_word_szB == 8) host_word_type = Ity_I64;
Top-level BB to IR conversion fn.
--------------------------------------------------------------- */
-/* See detailed comment in bb_to_IR.c. */
+/* See detailed comment in guest_generic_bb_to_IR.c. */
extern
IRSB* bb_to_IR (
/*OUT*/VexGuestExtents* vge,
/*OUT*/UInt* n_sc_extents,
/*OUT*/UInt* n_guest_instrs, /* stats only */
+ /*MOD*/VexRegisterUpdates* pxControl,
/*IN*/ void* callback_opaque,
/*IN*/ DisOneInstrFn dis_instr_fn,
/*IN*/ const UChar* guest_code,
/*IN*/ const VexArchInfo* archinfo_guest,
/*IN*/ const VexAbiInfo* abiinfo_both,
/*IN*/ IRType guest_word_type,
- /*IN*/ UInt (*needs_self_check)(void*,const VexGuestExtents*),
+ /*IN*/ UInt (*needs_self_check)
+ (void*, /*MB_MOD*/VexRegisterUpdates*,
+ const VexGuestExtents*),
/*IN*/ Bool (*preamble_function)(void*,IRSB*),
/*IN*/ Int offB_GUEST_CMSTART,
/*IN*/ Int offB_GUEST_CMLEN,
/* Describes to the optimser which part of the guest state require
precise memory exceptions. This is logically part of the guest
state description. */
-extern Bool guest_mips32_state_requires_precise_mem_exns ( Int, Int );
+extern
+Bool guest_mips32_state_requires_precise_mem_exns ( Int, Int,
+ VexRegisterUpdates );
-extern Bool guest_mips64_state_requires_precise_mem_exns ( Int, Int );
+extern
+Bool guest_mips64_state_requires_precise_mem_exns ( Int, Int,
+ VexRegisterUpdates );
extern VexGuestLayout mips32Guest_layout;
extern VexGuestLayout mips64Guest_layout;
Only SP is needed in mode VexRegUpdSpAtMemAccess.
*/
-Bool guest_mips32_state_requires_precise_mem_exns(Int minoff, Int maxoff)
+Bool guest_mips32_state_requires_precise_mem_exns (
+ Int minoff, Int maxoff, VexRegisterUpdates pxControl
+ )
{
Int sp_min = offsetof(VexGuestMIPS32State, guest_r29);
Int sp_max = sp_min + 4 - 1;
if (maxoff < sp_min || minoff > sp_max) {
/* no overlap with sp */
- if (vex_control.iropt_register_updates == VexRegUpdSpAtMemAccess)
+ if (pxControl == VexRegUpdSpAtMemAccess)
return False; /* We only need to check stack pointer. */
} else {
return True;
return False;
}
-Bool guest_mips64_state_requires_precise_mem_exns ( Int minoff, Int maxoff )
+Bool guest_mips64_state_requires_precise_mem_exns (
+ Int minoff, Int maxoff, VexRegisterUpdates pxControl
+ )
{
Int sp_min = offsetof(VexGuestMIPS64State, guest_r29);
Int sp_max = sp_min + 8 - 1;
if ( maxoff < sp_min || minoff > sp_max ) {
/* no overlap with sp */
- if (vex_control.iropt_register_updates == VexRegUpdSpAtMemAccess)
+ if (pxControl == VexRegUpdSpAtMemAccess)
return False; /* We only need to check stack pointer. */
} else {
return True;
precise memory exceptions. This is logically part of the guest
state description. */
extern
-Bool guest_ppc32_state_requires_precise_mem_exns ( Int, Int );
+Bool guest_ppc32_state_requires_precise_mem_exns ( Int, Int,
+ VexRegisterUpdates );
extern
-Bool guest_ppc64_state_requires_precise_mem_exns ( Int, Int );
+Bool guest_ppc64_state_requires_precise_mem_exns ( Int, Int,
+ VexRegisterUpdates );
extern
VexGuestLayout ppc32Guest_layout;
Only R1 is needed in mode VexRegUpdSpAtMemAccess.
*/
-Bool guest_ppc32_state_requires_precise_mem_exns ( Int minoff,
- Int maxoff )
+Bool guest_ppc32_state_requires_precise_mem_exns (
+ Int minoff, Int maxoff, VexRegisterUpdates pxControl
+ )
{
Int lr_min = offsetof(VexGuestPPC32State, guest_LR);
Int lr_max = lr_min + 4 - 1;
if (maxoff < r1_min || minoff > r1_max) {
/* no overlap with R1 */
- if (vex_control.iropt_register_updates == VexRegUpdSpAtMemAccess)
+ if (pxControl == VexRegUpdSpAtMemAccess)
return False; // We only need to check stack pointer.
} else {
return True;
return False;
}
-Bool guest_ppc64_state_requires_precise_mem_exns ( Int minoff,
- Int maxoff )
+Bool guest_ppc64_state_requires_precise_mem_exns (
+ Int minoff, Int maxoff, VexRegisterUpdates pxControl
+ )
{
/* Given that R2 is a Big Deal in the ELF ppc64 ABI, it seems
prudent to be conservative with it, even though thus far there
if (maxoff < r1_min || minoff > r1_max) {
/* no overlap with R1 */
- if (vex_control.iropt_register_updates == VexRegUpdSpAtMemAccess)
+ if (pxControl == VexRegUpdSpAtMemAccess)
return False; // We only need to check stack pointer.
} else {
return True;
Int n_precedingStmts);
-/* Describes to the optimser which part of the guest state require
+/* Describes to the optimiser which part of the guest state require
precise memory exceptions. This is logically part of the guest
state description. */
-Bool guest_s390x_state_requires_precise_mem_exns ( Int, Int );
+Bool guest_s390x_state_requires_precise_mem_exns ( Int, Int,
+ VexRegisterUpdates );
extern VexGuestLayout s390xGuest_layout;
.. maxoff requires precise memory exceptions. If in doubt return
True (but this generates significantly slower code). */
Bool
-guest_s390x_state_requires_precise_mem_exns(Int minoff, Int maxoff)
+guest_s390x_state_requires_precise_mem_exns (
+ Int minoff, Int maxoff, VexRegisterUpdates pxControl
+)
{
Int lr_min = S390X_GUEST_OFFSET(guest_LR);
Int lr_max = lr_min + 8 - 1;
if (maxoff < sp_min || minoff > sp_max) {
/* No overlap with SP */
- if (vex_control.iropt_register_updates == VexRegUpdSpAtMemAccess)
+ if (pxControl == VexRegUpdSpAtMemAccess)
return False; // We only need to check stack pointer.
} else {
return True;
precise memory exceptions. This is logically part of the guest
state description. */
extern
-Bool guest_x86_state_requires_precise_mem_exns ( Int, Int );
+Bool guest_x86_state_requires_precise_mem_exns ( Int, Int,
+ VexRegisterUpdates );
extern
VexGuestLayout x86guest_layout;
Only %ESP is needed in mode VexRegUpdSpAtMemAccess.
*/
-Bool guest_x86_state_requires_precise_mem_exns ( Int minoff,
- Int maxoff)
+Bool guest_x86_state_requires_precise_mem_exns (
+ Int minoff, Int maxoff, VexRegisterUpdates pxControl
+ )
{
Int ebp_min = offsetof(VexGuestX86State, guest_EBP);
Int ebp_max = ebp_min + 4 - 1;
if (maxoff < esp_min || minoff > esp_max) {
/* no overlap with esp */
- if (vex_control.iropt_register_updates == VexRegUpdSpAtMemAccess)
+ if (pxControl == VexRegUpdSpAtMemAccess)
return False; // We only need to check stack pointer.
} else {
return True;
static void handle_gets_Stmt (
HashHW* env,
IRStmt* st,
- Bool (*preciseMemExnsFn)(Int,Int)
+ Bool (*preciseMemExnsFn)(Int,Int,VexRegisterUpdates),
+ VexRegisterUpdates pxControl
)
{
Int j;
of the environment corresponding to guest state that may not
be reordered with respect to memory references. That means
at least the stack pointer. */
- switch (vex_control.iropt_register_updates) {
+ switch (pxControl) {
case VexRegUpdAllregsAtMemAccess:
/* Precise exceptions required at mem access.
Flush all guest state. */
preciseMemExnsFn. */
HWord k_lo = (env->key[j] >> 16) & 0xFFFF;
HWord k_hi = env->key[j] & 0xFFFF;
- if (preciseMemExnsFn( k_lo, k_hi ))
+ if (preciseMemExnsFn( k_lo, k_hi, pxControl ))
env->inuse[j] = False;
}
break;
case VexRegUpdAllregsAtEachInsn:
// VexRegUpdAllregsAtEachInsn cannot happen here.
// fall through
+ case VexRegUpd_INVALID:
default:
vassert(0);
}
static void redundant_put_removal_BB (
IRSB* bb,
- Bool (*preciseMemExnsFn)(Int,Int)
+ Bool (*preciseMemExnsFn)(Int,Int,VexRegisterUpdates),
+ VexRegisterUpdates pxControl
)
{
Int i, j;
IRStmt* st;
UInt key = 0; /* keep gcc -O happy */
- vassert(vex_control.iropt_register_updates < VexRegUpdAllregsAtEachInsn);
+ vassert(pxControl < VexRegUpdAllregsAtEachInsn);
HashHW* env = newHHW();
of the guest state is no longer a write, but a read. Also
deals with implicit reads of guest state needed to maintain
precise exceptions. */
- handle_gets_Stmt( env, st, preciseMemExnsFn );
+ handle_gets_Stmt( env, st, preciseMemExnsFn, pxControl );
}
}
bb is modified in-place. */
static
-void do_redundant_PutI_elimination ( IRSB* bb )
+void do_redundant_PutI_elimination ( IRSB* bb, VexRegisterUpdates pxControl )
{
Int i, j;
Bool delete;
IRStmt *st, *stj;
- vassert(vex_control.iropt_register_updates < VexRegUpdAllregsAtEachInsn);
+ vassert(pxControl < VexRegUpdAllregsAtEachInsn);
for (i = 0; i < bb->stmts_used; i++) {
st = bb->stmts[i];
}
inline
-static Interval dirty_helper_puts ( const IRDirty *d,
- Bool (*preciseMemExnsFn)(Int, Int),
- Bool *requiresPreciseMemExns )
+static Interval dirty_helper_puts (
+ const IRDirty *d,
+ Bool (*preciseMemExnsFn)(Int,Int,VexRegisterUpdates),
+ VexRegisterUpdates pxControl,
+ /*OUT*/Bool *requiresPreciseMemExns
+ )
{
Int i;
Interval interval;
Int repeatLen = d->fxState[i].repeatLen;
if (preciseMemExnsFn(offset,
- offset + nRepeats * repeatLen + size - 1)) {
+ offset + nRepeats * repeatLen + size - 1,
+ pxControl)) {
*requiresPreciseMemExns = True;
}
update_interval(&interval, offset,
return interval;
}
-/* Return an interval if st modifies the guest state. Via requiresPreciseMemExns
- return whether or not that modification requires precise exceptions. */
-static Interval stmt_modifies_guest_state ( IRSB *bb, const IRStmt *st,
- Bool (*preciseMemExnsFn)(Int,Int),
- Bool *requiresPreciseMemExns )
+/* Return an interval if st modifies the guest state. Via
+ requiresPreciseMemExns return whether or not that modification
+ requires precise exceptions. */
+static Interval stmt_modifies_guest_state (
+ IRSB *bb, const IRStmt *st,
+ Bool (*preciseMemExnsFn)(Int,Int,VexRegisterUpdates),
+ VexRegisterUpdates pxControl,
+ /*OUT*/Bool *requiresPreciseMemExns
+ )
{
Interval interval;
Int offset = st->Ist.Put.offset;
Int size = sizeofIRType(typeOfIRExpr(bb->tyenv, st->Ist.Put.data));
- *requiresPreciseMemExns = preciseMemExnsFn(offset, offset + size - 1);
+ *requiresPreciseMemExns
+ = preciseMemExnsFn(offset, offset + size - 1, pxControl);
interval.present = True;
interval.low = offset;
interval.high = offset + size - 1;
are no holes. This is to avoid a loop. The assumption is conservative
in the sense that we might report that precise memory exceptions are
needed when in fact they are not. */
- *requiresPreciseMemExns =
- preciseMemExnsFn(offset, offset + descr->nElems * size - 1);
+ *requiresPreciseMemExns
+ = preciseMemExnsFn(offset, offset + descr->nElems * size - 1,
+ pxControl);
interval.present = True;
interval.low = offset;
interval.high = offset + descr->nElems * size - 1;
}
case Ist_Dirty:
- return dirty_helper_puts(st->Ist.Dirty.details, preciseMemExnsFn,
+ return dirty_helper_puts(st->Ist.Dirty.details,
+ preciseMemExnsFn, pxControl,
requiresPreciseMemExns);
default:
}
}
-/* notstatic */ Addr ado_treebuild_BB ( IRSB* bb,
- Bool (*preciseMemExnsFn)(Int,Int) )
+/* notstatic */ Addr ado_treebuild_BB (
+ IRSB* bb,
+ Bool (*preciseMemExnsFn)(Int,Int,VexRegisterUpdates),
+ VexRegisterUpdates pxControl
+ )
{
Int i, j, k, m;
Bool stmtStores, invalidateMe;
consideration does, or might do (sidely safe @ True). */
Bool putRequiresPreciseMemExns;
- putInterval = stmt_modifies_guest_state( bb, st, preciseMemExnsFn,
- &putRequiresPreciseMemExns);
+ putInterval = stmt_modifies_guest_state(
+ bb, st, preciseMemExnsFn, pxControl,
+ &putRequiresPreciseMemExns
+ );
/* be True if this stmt writes memory or might do (==> we don't
want to reorder other loads or stores relative to it). Also,
IRSB* cheap_transformations (
IRSB* bb,
IRExpr* (*specHelper) (const HChar*, IRExpr**, IRStmt**, Int),
- Bool (*preciseMemExnsFn)(Int,Int)
+ Bool (*preciseMemExnsFn)(Int,Int,VexRegisterUpdates),
+ VexRegisterUpdates pxControl
)
{
redundant_get_removal_BB ( bb );
ppIRSB(bb);
}
- if (vex_control.iropt_register_updates < VexRegUpdAllregsAtEachInsn) {
- redundant_put_removal_BB ( bb, preciseMemExnsFn );
+ if (pxControl < VexRegUpdAllregsAtEachInsn) {
+ redundant_put_removal_BB ( bb, preciseMemExnsFn, pxControl );
}
if (iropt_verbose) {
vex_printf("\n========= REDUNDANT PUT\n\n" );
optimising as much as possible in the presence of GetI and PutI. */
static
-IRSB* expensive_transformations( IRSB* bb )
+IRSB* expensive_transformations( IRSB* bb, VexRegisterUpdates pxControl )
{
(void)do_cse_BB( bb );
collapse_AddSub_chains_BB( bb );
do_redundant_GetI_elimination( bb );
- if (vex_control.iropt_register_updates < VexRegUpdAllregsAtEachInsn) {
- do_redundant_PutI_elimination( bb );
+ if (pxControl < VexRegUpdAllregsAtEachInsn) {
+ do_redundant_PutI_elimination( bb, pxControl );
}
do_deadcode_BB( bb );
return bb;
IRSB* do_iropt_BB(
IRSB* bb0,
IRExpr* (*specHelper) (const HChar*, IRExpr**, IRStmt**, Int),
- Bool (*preciseMemExnsFn)(Int,Int),
+ Bool (*preciseMemExnsFn)(Int,Int,VexRegisterUpdates),
+ VexRegisterUpdates pxControl,
Addr guest_addr,
VexArch guest_arch
)
If needed, do expensive transformations and then another cheap
cleanup pass. */
- bb = cheap_transformations( bb, specHelper, preciseMemExnsFn );
+ bb = cheap_transformations( bb, specHelper, preciseMemExnsFn, pxControl );
if (guest_arch == VexArchARM) {
/* Translating Thumb2 code produces a lot of chaff. We have to
work extra hard to get rid of it. */
bb = cprop_BB(bb);
bb = spec_helpers_BB ( bb, specHelper );
- if (vex_control.iropt_register_updates < VexRegUpdAllregsAtEachInsn) {
- redundant_put_removal_BB ( bb, preciseMemExnsFn );
+ if (pxControl < VexRegUpdAllregsAtEachInsn) {
+ redundant_put_removal_BB ( bb, preciseMemExnsFn, pxControl );
}
do_cse_BB( bb );
do_deadcode_BB( bb );
n_expensive++;
if (DEBUG_IROPT)
vex_printf("***** EXPENSIVE %d %d\n", n_total, n_expensive);
- bb = expensive_transformations( bb );
- bb = cheap_transformations( bb, specHelper, preciseMemExnsFn );
+ bb = expensive_transformations( bb, pxControl );
+ bb = cheap_transformations( bb, specHelper,
+ preciseMemExnsFn, pxControl );
/* Potentially common up GetIs */
cses = do_cse_BB( bb );
if (cses)
- bb = cheap_transformations( bb, specHelper, preciseMemExnsFn );
+ bb = cheap_transformations( bb, specHelper,
+ preciseMemExnsFn, pxControl );
}
/* Now have a go at unrolling simple (single-BB) loops. If
bb2 = maybe_loop_unroll_BB( bb, guest_addr );
if (bb2) {
- bb = cheap_transformations( bb2, specHelper, preciseMemExnsFn );
+ bb = cheap_transformations( bb2, specHelper,
+ preciseMemExnsFn, pxControl );
if (hasGetIorPutI) {
- bb = expensive_transformations( bb );
- bb = cheap_transformations( bb, specHelper, preciseMemExnsFn );
+ bb = expensive_transformations( bb, pxControl );
+ bb = cheap_transformations( bb, specHelper,
+ preciseMemExnsFn, pxControl );
} else {
/* at least do CSE and dead code removal */
do_cse_BB( bb );
#include "libvex.h"
/* Top level optimiser entry point. Returns a new BB. Operates
- under the control of the global "vex_control" struct. */
+ under the control of the global "vex_control" struct and of the
+ supplied |pxControl| argument. */
extern
-IRSB* do_iropt_BB(
+IRSB* do_iropt_BB (
IRSB* bb,
IRExpr* (*specHelper) (const HChar*, IRExpr**, IRStmt**, Int),
- Bool (*preciseMemExnsFn)(Int,Int),
+ Bool (*preciseMemExnsFn)(Int,Int,VexRegisterUpdates),
+ VexRegisterUpdates pxControl,
Addr guest_addr,
VexArch guest_arch
);
/* The tree-builder. Make (approximately) maximal safe trees. bb is
destructively modified. Returns (unrelatedly, but useful later on)
the guest address of the highest addressed byte from any insn in
- this block, or Addr64_MAX if unknown (can that ever happen?) */
+ this block, or Addr_MAX if unknown (can that ever happen?) */
extern
-Addr ado_treebuild_BB ( IRSB* bb, Bool (*preciseMemExnsFn)(Int,Int) );
+Addr ado_treebuild_BB (
+ IRSB* bb,
+ Bool (*preciseMemExnsFn)(Int,Int,VexRegisterUpdates),
+ VexRegisterUpdates pxControl
+ );
#endif /* ndef __VEX_IR_OPT_H */
void LibVEX_default_VexControl ( /*OUT*/ VexControl* vcon )
{
vex_bzero(vcon, sizeof(*vcon));
- vcon->iropt_verbosity = 0;
- vcon->iropt_level = 2;
- vcon->iropt_register_updates = VexRegUpdUnwindregsAtMemAccess;
- vcon->iropt_unroll_thresh = 120;
- vcon->guest_max_insns = 60;
- vcon->guest_chase_thresh = 10;
- vcon->guest_chase_cond = False;
+ vcon->iropt_verbosity = 0;
+ vcon->iropt_level = 2;
+ vcon->iropt_register_updates_default = VexRegUpdUnwindregsAtMemAccess;
+ vcon->iropt_unroll_thresh = 120;
+ vcon->guest_max_insns = 60;
+ vcon->guest_chase_thresh = 10;
+ vcon->guest_chase_cond = False;
}
const void*, const void*, const void*,
const void* );
IRExpr* (*specHelper) ( const HChar*, IRExpr**, IRStmt**, Int );
- Bool (*preciseMemExnsFn) ( Int, Int );
+ Bool (*preciseMemExnsFn) ( Int, Int, VexRegisterUpdates );
DisOneInstrFn disInstrFn;
" Front end "
"------------------------\n\n");
+ VexRegisterUpdates pxControl = vex_control.iropt_register_updates_default;
+ vassert(pxControl >= VexRegUpdSpAtMemAccess
+ && pxControl <= VexRegUpdAllregsAtEachInsn);
+
irsb = bb_to_IR ( vta->guest_extents,
&res.n_sc_extents,
&res.n_guest_instrs,
+ &pxControl,
vta->callback_opaque,
disInstrFn,
vta->guest_bytes,
vassert(vta->guest_extents->len[i] < 10000); /* sanity */
}
+ /* bb_to_IR() could have caused pxControl to change. */
+ vassert(pxControl >= VexRegUpdSpAtMemAccess
+ && pxControl <= VexRegUpdAllregsAtEachInsn);
+
/* If debugging, show the raw guest bytes for this bb. */
if (0 || (vex_traceflags & VEX_TRACE_FE)) {
if (vta->guest_extents->n_used > 1) {
vexAllocSanityCheck();
/* Clean it up, hopefully a lot. */
- irsb = do_iropt_BB ( irsb, specHelper, preciseMemExnsFn,
+ irsb = do_iropt_BB ( irsb, specHelper, preciseMemExnsFn, pxControl,
vta->guest_bytes_addr,
vta->arch_guest );
sanityCheckIRSB( irsb, "after initial iropt",
/* Turn it into virtual-registerised code. Build trees -- this
also throws away any dead bindings. */
- max_ga = ado_treebuild_BB( irsb, preciseMemExnsFn );
+ max_ga = ado_treebuild_BB( irsb, preciseMemExnsFn, pxControl );
if (vta->finaltidy) {
irsb = vta->finaltidy(irsb);
/* VexRegisterUpdates specifies when to ensure that the guest state is
- up to date.
-
- VexRegUpdSpAtMemAccess : all registers are updated at superblock
- exits, SP is up to date at memory exception points. The SP is described
- by the arch specific functions guest_<arch>_state_requires_precise_mem_exns.
-
- VexRegUpdUnwindregsAtMemAccess : registers needed to make a stack trace are
- up to date at memory exception points. Typically, these are PC/SP/FP. The
- minimal registers are described by the arch specific functions
- guest_<arch>_state_requires_precise_mem_exns.
-
- VexRegUpdAllregsAtMemAccess : all registers up to date at memory exception
- points.
-
- VexRegUpdAllregsAtEachInsn : all registers up to date at each instruction. */
-typedef enum { VexRegUpdSpAtMemAccess=0x700,
- VexRegUpdUnwindregsAtMemAccess,
- VexRegUpdAllregsAtMemAccess,
- VexRegUpdAllregsAtEachInsn } VexRegisterUpdates;
+ up to date, in order of increasing accuracy but increasing expense.
+
+ VexRegUpdSpAtMemAccess: all registers are updated at superblock
+ exits, and SP is also up to date at memory exception points. The
+ SP is described by the arch specific functions
+ guest_<arch>_state_requires_precise_mem_exns.
+
+ VexRegUpdUnwindregsAtMemAccess: registers needed to make a stack
+ trace are up to date at memory exception points. Typically,
+ these are PC/SP/FP. The minimal registers are described by the
+ arch specific functions guest_<arch>_state_requires_precise_mem_exns.
+ This is what Valgrind sets as the default.
+
+ VexRegUpdAllregsAtMemAccess: all registers up to date at memory
+ exception points. This is what normally might be considered as
+ providing "precise exceptions for memory", but does not
+ necessarily provide precise register values at any other kind of
+ exception.
+
+ VexRegUpdAllregsAtEachInsn: all registers up to date at each
+ instruction.
+*/
+typedef
+ enum {
+ VexRegUpd_INVALID=0x700,
+ VexRegUpdSpAtMemAccess,
+ VexRegUpdUnwindregsAtMemAccess,
+ VexRegUpdAllregsAtMemAccess,
+ VexRegUpdAllregsAtEachInsn
+ }
+ VexRegisterUpdates;
/* Control of Vex's optimiser. */
/* Control aggressiveness of iropt. 0 = no opt, 1 = simple
opts, 2 (default) = max optimisation. */
Int iropt_level;
- /* Controls when registers are updated in guest state. */
- VexRegisterUpdates iropt_register_updates;
+ /* Controls when registers are updated in guest state. Note
+ that this is the default value. The VEX client can override
+ this on a per-IRSB basis if it wants. bb_to_IR() will query
+ the client to ask if it wants a different setting for the
+ block under construction, and that new setting is transported
+ back to LibVEX_Translate, which feeds it to iropt via the
+ various do_iropt_BB calls. */
+ VexRegisterUpdates iropt_register_updates_default;
/* How aggressive should iropt be in unrolling loops? Higher
numbers make it more enthusiastic about loop unrolling.
Default=120. A setting of zero disables unrolling. */
if any, a self check is required for. Must not be NULL.
The returned value is a bitmask with a 1 in position i indicating
that the i'th extent needs a check. Since there can be at most
- 3 extents, the returned values must be between 0 and 7. */
+ 3 extents, the returned values must be between 0 and 7.
+
+ This call also gives the VEX client the opportunity to change
+ the precision of register update preservation as performed by
+ the IR optimiser. Before the call, VEX will set *pxControl
+ to hold the default register-update status value as specified
+ by VexControl::iropt_register_updates_default as passed to
+ LibVEX_Init at library initialisation time. The client (in
+ this callback) can if it wants, inspect the value and change
+ it to something different, and that value will be used for
+ subsequent IR optimisation of the block. */
UInt (*needs_self_check)( /*callback_opaque*/void*,
+ /*MAYBE_MOD*/VexRegisterUpdates* pxControl,
const VexGuestExtents* );
/* IN: optionally, a callback which allows the caller to add its