From: Julian Seward Date: Thu, 5 Feb 2015 12:53:20 +0000 (+0000) Subject: Make a very minor change to the LibVEX_Translate interface (sub-arg of X-Git-Tag: svn/VALGRIND_3_11_0^2~98 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=b3ec739ac7dce06059a77bf994eda2953922ceca;p=thirdparty%2Fvalgrind.git 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 --- diff --git a/VEX/priv/guest_amd64_defs.h b/VEX/priv/guest_amd64_defs.h index 8ccce6f75e..003ebde9a4 100644 --- a/VEX/priv/guest_amd64_defs.h +++ b/VEX/priv/guest_amd64_defs.h @@ -74,7 +74,8 @@ IRExpr* guest_amd64_spechelper ( const HChar* function_name, 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/VEX/priv/guest_amd64_helpers.c b/VEX/priv/guest_amd64_helpers.c index 680a207a9d..aa1f2d5d95 100644 --- a/VEX/priv/guest_amd64_helpers.c +++ b/VEX/priv/guest_amd64_helpers.c @@ -3988,8 +3988,9 @@ void LibVEX_GuestAMD64_initialise ( /*OUT*/VexGuestAMD64State* vex_state ) 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 @@ Bool guest_amd64_state_requires_precise_mem_exns ( Int minoff, 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/VEX/priv/guest_arm64_defs.h b/VEX/priv/guest_arm64_defs.h index 8910cad829..a3431f0739 100644 --- a/VEX/priv/guest_arm64_defs.h +++ b/VEX/priv/guest_arm64_defs.h @@ -64,7 +64,8 @@ IRExpr* guest_arm64_spechelper ( const HChar* function_name, 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/VEX/priv/guest_arm64_helpers.c b/VEX/priv/guest_arm64_helpers.c index 5d2080e6ed..e8dda647b4 100644 --- a/VEX/priv/guest_arm64_helpers.c +++ b/VEX/priv/guest_arm64_helpers.c @@ -1317,8 +1317,9 @@ void LibVEX_GuestARM64_initialise ( /*OUT*/VexGuestARM64State* vex_state ) 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 @@ Bool guest_arm64_state_requires_precise_mem_exns ( Int minoff, 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/VEX/priv/guest_arm_defs.h b/VEX/priv/guest_arm_defs.h index abefb64167..b5b012b82c 100644 --- a/VEX/priv/guest_arm_defs.h +++ b/VEX/priv/guest_arm_defs.h @@ -66,7 +66,8 @@ IRExpr* guest_arm_spechelper ( const HChar* function_name, 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/VEX/priv/guest_arm_helpers.c b/VEX/priv/guest_arm_helpers.c index 2eeb13a0f0..8a9b7f93d2 100644 --- a/VEX/priv/guest_arm_helpers.c +++ b/VEX/priv/guest_arm_helpers.c @@ -1047,8 +1047,9 @@ void LibVEX_GuestARM_initialise ( /*OUT*/VexGuestARMState* vex_state ) 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 @@ Bool guest_arm_state_requires_precise_mem_exns ( Int minoff, 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/VEX/priv/guest_generic_bb_to_IR.c b/VEX/priv/guest_generic_bb_to_IR.c index 1b6a063825..bb37d96f77 100644 --- a/VEX/priv/guest_generic_bb_to_IR.c +++ b/VEX/priv/guest_generic_bb_to_IR.c @@ -181,6 +181,7 @@ 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, @@ -192,7 +193,9 @@ IRSB* bb_to_IR ( /*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 @@ IRSB* bb_to_IR ( 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/VEX/priv/guest_generic_bb_to_IR.h b/VEX/priv/guest_generic_bb_to_IR.h index 7a7c1369e0..49c94d79b4 100644 --- a/VEX/priv/guest_generic_bb_to_IR.h +++ b/VEX/priv/guest_generic_bb_to_IR.h @@ -165,12 +165,13 @@ typedef 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 @@ IRSB* bb_to_IR ( /*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/VEX/priv/guest_mips_defs.h b/VEX/priv/guest_mips_defs.h index 757211d8e7..c60e026bfc 100644 --- a/VEX/priv/guest_mips_defs.h +++ b/VEX/priv/guest_mips_defs.h @@ -68,9 +68,13 @@ extern IRExpr *guest_mips64_spechelper ( const HChar * function_name, /* 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/VEX/priv/guest_mips_helpers.c b/VEX/priv/guest_mips_helpers.c index 0b10208830..863efda833 100644 --- a/VEX/priv/guest_mips_helpers.c +++ b/VEX/priv/guest_mips_helpers.c @@ -287,7 +287,9 @@ void LibVEX_GuestMIPS64_initialise ( /*OUT*/ VexGuestMIPS64State * vex_state ) 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 @@ Bool guest_mips32_state_requires_precise_mem_exns(Int minoff, Int maxoff) 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 @@ Bool guest_mips32_state_requires_precise_mem_exns(Int minoff, Int maxoff) 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 @@ Bool guest_mips64_state_requires_precise_mem_exns ( Int minoff, Int maxoff ) 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/VEX/priv/guest_ppc_defs.h b/VEX/priv/guest_ppc_defs.h index 55bb656095..8ef17065ad 100644 --- a/VEX/priv/guest_ppc_defs.h +++ b/VEX/priv/guest_ppc_defs.h @@ -81,10 +81,12 @@ IRExpr* guest_ppc64_spechelper ( const HChar* function_name, 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/VEX/priv/guest_ppc_helpers.c b/VEX/priv/guest_ppc_helpers.c index 18a1ac3fa7..dc36818b31 100644 --- a/VEX/priv/guest_ppc_helpers.c +++ b/VEX/priv/guest_ppc_helpers.c @@ -711,8 +711,9 @@ void LibVEX_GuestPPC64_initialise ( /*OUT*/VexGuestPPC64State* vex_state ) 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 @@ Bool guest_ppc32_state_requires_precise_mem_exns ( Int minoff, 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 @@ Bool guest_ppc32_state_requires_precise_mem_exns ( Int minoff, 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 @@ Bool guest_ppc64_state_requires_precise_mem_exns ( Int minoff, 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/VEX/priv/guest_s390_defs.h b/VEX/priv/guest_s390_defs.h index 2e482f59a3..758cf91b00 100644 --- a/VEX/priv/guest_s390_defs.h +++ b/VEX/priv/guest_s390_defs.h @@ -60,10 +60,11 @@ IRExpr* guest_s390x_spechelper ( const HChar *function_name, 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/VEX/priv/guest_s390_helpers.c b/VEX/priv/guest_s390_helpers.c index df1f24bb65..cf223c484e 100644 --- a/VEX/priv/guest_s390_helpers.c +++ b/VEX/priv/guest_s390_helpers.c @@ -152,7 +152,9 @@ LibVEX_GuestS390X_initialise(VexGuestS390XState *state) .. 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 @@ guest_s390x_state_requires_precise_mem_exns(Int minoff, Int maxoff) 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/VEX/priv/guest_x86_defs.h b/VEX/priv/guest_x86_defs.h index 3dc34c8bc3..412ee94007 100644 --- a/VEX/priv/guest_x86_defs.h +++ b/VEX/priv/guest_x86_defs.h @@ -74,7 +74,8 @@ IRExpr* guest_x86_spechelper ( const HChar* function_name, 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/VEX/priv/guest_x86_helpers.c b/VEX/priv/guest_x86_helpers.c index ef5e09e720..66a571fd93 100644 --- a/VEX/priv/guest_x86_helpers.c +++ b/VEX/priv/guest_x86_helpers.c @@ -2778,8 +2778,9 @@ void LibVEX_GuestX86_initialise ( /*OUT*/VexGuestX86State* vex_state ) 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 @@ Bool guest_x86_state_requires_precise_mem_exns ( Int minoff, 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/VEX/priv/ir_opt.c b/VEX/priv/ir_opt.c index 86bd6464bd..ffd18f95be 100644 --- a/VEX/priv/ir_opt.c +++ b/VEX/priv/ir_opt.c @@ -716,7 +716,8 @@ static void redundant_get_removal_BB ( IRSB* bb ) 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 @@ static void handle_gets_Stmt ( 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 @@ static void handle_gets_Stmt ( 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 handle_gets_Stmt ( 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 @@ static void redundant_put_removal_BB ( 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 @@ static void redundant_put_removal_BB ( 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 @@ void do_redundant_GetI_elimination ( IRSB* bb ) 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 @@ static Bool dirty_helper_stores ( const IRDirty *d ) } 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 @@ static Interval dirty_helper_puts ( const IRDirty *d, 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 @@ static Interval dirty_helper_puts ( const IRDirty *d, 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 @@ static Interval stmt_modifies_guest_state ( IRSB *bb, const IRStmt *st, 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 @@ static Interval stmt_modifies_guest_state ( IRSB *bb, const IRStmt *st, 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 @@ static Interval stmt_modifies_guest_state ( IRSB *bb, const IRStmt *st, } 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 @@ static Interval stmt_modifies_guest_state ( IRSB *bb, const IRStmt *st, } } -/* 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 @@ static Interval stmt_modifies_guest_state ( IRSB *bb, const IRStmt *st, 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 @@ static 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 @@ IRSB* cheap_transformations ( 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 @@ IRSB* cheap_transformations ( 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 @@ static void considerExpensives ( /*OUT*/Bool* hasGetIorPutI, 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 @@ IRSB* do_iropt_BB( 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 @@ IRSB* do_iropt_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 @@ -6118,10 +6141,12 @@ IRSB* do_iropt_BB( 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/VEX/priv/ir_opt.h b/VEX/priv/ir_opt.h index 07cee63b61..43b2a47260 100644 --- a/VEX/priv/ir_opt.h +++ b/VEX/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 @@ void do_deadcode_BB ( IRSB* bb ); /* 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/VEX/priv/main_main.c b/VEX/priv/main_main.c index 71c8bf665a..e76a5e489d 100644 --- a/VEX/priv/main_main.c +++ b/VEX/priv/main_main.c @@ -94,13 +94,13 @@ static Int sdiv32 ( Int x, Int y ) { return x/y; } 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 @@ VexTranslateResult LibVEX_Translate ( VexTranslateArgs* vta ) 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 @@ VexTranslateResult LibVEX_Translate ( VexTranslateArgs* vta ) " 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 @@ VexTranslateResult LibVEX_Translate ( VexTranslateArgs* vta ) 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 @@ VexTranslateResult LibVEX_Translate ( VexTranslateArgs* vta ) 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 @@ VexTranslateResult LibVEX_Translate ( VexTranslateArgs* vta ) /* 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/VEX/pub/libvex.h b/VEX/pub/libvex.h index 3e99d47020..0138999fe2 100644 --- a/VEX/pub/libvex.h +++ b/VEX/pub/libvex.h @@ -386,25 +386,37 @@ void LibVEX_default_VexAbiInfo ( /*OUT*/VexAbiInfo* vbi ); /* 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__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__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__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__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. */ @@ -415,8 +427,14 @@ typedef /* 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 @@ typedef 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