Make a very minor change to the LibVEX_Translate interface (sub-arg of
needs_self_check) which allows VEX's user to selectively override, on
a per-translation basis, the default precise-exception control setting
that is specified in VexControl::iropt_register_updates. Fix up
plumbing inside iropt so as to used passed-in values rather than the
default one.
git-svn-id: svn://svn.valgrind.org/vex/trunk@3084 8f6e269a-dfd6-0310-a8e1-e2731360e62c
diff --git a/priv/guest_amd64_defs.h b/priv/guest_amd64_defs.h
index 8ccce6f..003ebde 100644
--- a/priv/guest_amd64_defs.h
+++ b/priv/guest_amd64_defs.h
@@ -74,7 +74,8 @@
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;
diff --git a/priv/guest_amd64_helpers.c b/priv/guest_amd64_helpers.c
index 680a207..aa1f2d5 100644
--- a/priv/guest_amd64_helpers.c
+++ b/priv/guest_amd64_helpers.c
@@ -3988,8 +3988,9 @@
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;
@@ -4000,7 +4001,7 @@
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;
diff --git a/priv/guest_arm64_defs.h b/priv/guest_arm64_defs.h
index 8910cad..a3431f0 100644
--- a/priv/guest_arm64_defs.h
+++ b/priv/guest_arm64_defs.h
@@ -64,7 +64,8 @@
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;
diff --git a/priv/guest_arm64_helpers.c b/priv/guest_arm64_helpers.c
index 5d2080e..e8dda64 100644
--- a/priv/guest_arm64_helpers.c
+++ b/priv/guest_arm64_helpers.c
@@ -1317,8 +1317,9 @@
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;
@@ -1327,7 +1328,7 @@
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;
diff --git a/priv/guest_arm_defs.h b/priv/guest_arm_defs.h
index abefb64..b5b012b 100644
--- a/priv/guest_arm_defs.h
+++ b/priv/guest_arm_defs.h
@@ -66,7 +66,8 @@
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;
diff --git a/priv/guest_arm_helpers.c b/priv/guest_arm_helpers.c
index 2eeb13a..8a9b7f9 100644
--- a/priv/guest_arm_helpers.c
+++ b/priv/guest_arm_helpers.c
@@ -1047,8 +1047,9 @@
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;
@@ -1057,7 +1058,7 @@
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;
diff --git a/priv/guest_generic_bb_to_IR.c b/priv/guest_generic_bb_to_IR.c
index 1b6a063..bb37d96 100644
--- a/priv/guest_generic_bb_to_IR.c
+++ b/priv/guest_generic_bb_to_IR.c
@@ -181,6 +181,7 @@
/*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,
@@ -192,7 +193,9 @@
/*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,
@@ -528,7 +531,7 @@
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;
diff --git a/priv/guest_generic_bb_to_IR.h b/priv/guest_generic_bb_to_IR.h
index 7a7c136..49c94d7 100644
--- a/priv/guest_generic_bb_to_IR.h
+++ b/priv/guest_generic_bb_to_IR.h
@@ -165,12 +165,13 @@
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,
@@ -182,7 +183,9 @@
/*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,
diff --git a/priv/guest_mips_defs.h b/priv/guest_mips_defs.h
index 757211d..c60e026 100644
--- a/priv/guest_mips_defs.h
+++ b/priv/guest_mips_defs.h
@@ -68,9 +68,13 @@
/* 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;
diff --git a/priv/guest_mips_helpers.c b/priv/guest_mips_helpers.c
index 0b10208..863efda 100644
--- a/priv/guest_mips_helpers.c
+++ b/priv/guest_mips_helpers.c
@@ -287,7 +287,9 @@
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;
@@ -296,7 +298,7 @@
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;
@@ -322,7 +324,9 @@
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;
@@ -331,7 +335,7 @@
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;
diff --git a/priv/guest_ppc_defs.h b/priv/guest_ppc_defs.h
index 55bb656..8ef1706 100644
--- a/priv/guest_ppc_defs.h
+++ b/priv/guest_ppc_defs.h
@@ -81,10 +81,12 @@
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;
diff --git a/priv/guest_ppc_helpers.c b/priv/guest_ppc_helpers.c
index 18a1ac3..dc36818 100644
--- a/priv/guest_ppc_helpers.c
+++ b/priv/guest_ppc_helpers.c
@@ -711,8 +711,9 @@
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;
@@ -723,7 +724,7 @@
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;
@@ -744,8 +745,9 @@
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
@@ -762,7 +764,7 @@
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;
diff --git a/priv/guest_s390_defs.h b/priv/guest_s390_defs.h
index 2e482f5..758cf91 100644
--- a/priv/guest_s390_defs.h
+++ b/priv/guest_s390_defs.h
@@ -60,10 +60,11 @@
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;
diff --git a/priv/guest_s390_helpers.c b/priv/guest_s390_helpers.c
index df1f24b..cf223c4 100644
--- a/priv/guest_s390_helpers.c
+++ b/priv/guest_s390_helpers.c
@@ -152,7 +152,9 @@
.. 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;
@@ -165,7 +167,7 @@
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;
diff --git a/priv/guest_x86_defs.h b/priv/guest_x86_defs.h
index 3dc34c8..412ee94 100644
--- a/priv/guest_x86_defs.h
+++ b/priv/guest_x86_defs.h
@@ -74,7 +74,8 @@
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;
diff --git a/priv/guest_x86_helpers.c b/priv/guest_x86_helpers.c
index ef5e09e..66a571f 100644
--- a/priv/guest_x86_helpers.c
+++ b/priv/guest_x86_helpers.c
@@ -2778,8 +2778,9 @@
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;
@@ -2790,7 +2791,7 @@
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;
diff --git a/priv/ir_opt.c b/priv/ir_opt.c
index 86bd646..ffd18f9 100644
--- a/priv/ir_opt.c
+++ b/priv/ir_opt.c
@@ -716,7 +716,8 @@
static void handle_gets_Stmt (
HashHW* env,
IRStmt* st,
- Bool (*preciseMemExnsFn)(Int,Int)
+ Bool (*preciseMemExnsFn)(Int,Int,VexRegisterUpdates),
+ VexRegisterUpdates pxControl
)
{
Int j;
@@ -828,7 +829,7 @@
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. */
@@ -849,13 +850,14 @@
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);
}
@@ -882,7 +884,8 @@
static void redundant_put_removal_BB (
IRSB* bb,
- Bool (*preciseMemExnsFn)(Int,Int)
+ Bool (*preciseMemExnsFn)(Int,Int,VexRegisterUpdates),
+ VexRegisterUpdates pxControl
)
{
Int i, j;
@@ -890,7 +893,7 @@
IRStmt* st;
UInt key = 0; /* keep gcc -O happy */
- vassert(vex_control.iropt_register_updates < VexRegUpdAllregsAtEachInsn);
+ vassert(pxControl < VexRegUpdAllregsAtEachInsn);
HashHW* env = newHHW();
@@ -982,7 +985,7 @@
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 );
}
}
@@ -4392,13 +4395,13 @@
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];
@@ -5524,9 +5527,12 @@
}
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;
@@ -5558,7 +5564,8 @@
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,
@@ -5569,11 +5576,15 @@
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;
@@ -5582,7 +5593,8 @@
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;
@@ -5598,8 +5610,9 @@
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;
@@ -5607,7 +5620,8 @@
}
case Ist_Dirty:
- return dirty_helper_puts(st->Ist.Dirty.details, preciseMemExnsFn,
+ return dirty_helper_puts(st->Ist.Dirty.details,
+ preciseMemExnsFn, pxControl,
requiresPreciseMemExns);
default:
@@ -5619,8 +5633,11 @@
}
}
-/* 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;
@@ -5759,8 +5776,10 @@
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,
@@ -5860,7 +5879,8 @@
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 );
@@ -5869,8 +5889,8 @@
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" );
@@ -5904,13 +5924,13 @@
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;
@@ -6038,7 +6058,8 @@
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
)
@@ -6070,15 +6091,15 @@
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 );
@@ -6105,12 +6126,14 @@
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
@@ -6118,10 +6141,12 @@
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 );
diff --git a/priv/ir_opt.h b/priv/ir_opt.h
index 07cee63..43b2a47 100644
--- a/priv/ir_opt.h
+++ b/priv/ir_opt.h
@@ -41,12 +41,14 @@
#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
);
@@ -62,9 +64,13 @@
/* 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 */
diff --git a/priv/main_main.c b/priv/main_main.c
index 71c8bf6..e76a5e4 100644
--- a/priv/main_main.c
+++ b/priv/main_main.c
@@ -94,13 +94,13 @@
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;
}
@@ -229,7 +229,7 @@
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;
@@ -683,9 +683,14 @@
" 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,
@@ -719,6 +724,10 @@
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) {
@@ -746,7 +755,7 @@
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",
@@ -811,7 +820,7 @@
/* 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);
diff --git a/pub/libvex.h b/pub/libvex.h
index 3e99d47..0138999 100644
--- a/pub/libvex.h
+++ b/pub/libvex.h
@@ -386,25 +386,37 @@
/* VexRegisterUpdates specifies when to ensure that the guest state is
- up to date.
+ up to date, in order of increasing accuracy but increasing expense.
- 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.
+ 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.
+ 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.
+ 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 { VexRegUpdSpAtMemAccess=0x700,
- VexRegUpdUnwindregsAtMemAccess,
- VexRegUpdAllregsAtMemAccess,
- VexRegUpdAllregsAtEachInsn } VexRegisterUpdates;
+ VexRegUpdAllregsAtEachInsn: all registers up to date at each
+ instruction.
+*/
+typedef
+ enum {
+ VexRegUpd_INVALID=0x700,
+ VexRegUpdSpAtMemAccess,
+ VexRegUpdUnwindregsAtMemAccess,
+ VexRegUpdAllregsAtMemAccess,
+ VexRegUpdAllregsAtEachInsn
+ }
+ VexRegisterUpdates;
/* Control of Vex's optimiser. */
@@ -415,8 +427,14 @@
/* 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. */
@@ -642,8 +660,19 @@
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