From: Julian Seward Date: Mon, 25 Oct 2004 14:50:21 +0000 (+0000) Subject: Generic fixes to iropt to enable it to be as sloppy with exceptions as X-Git-Tag: svn/VALGRIND_3_0_1^2~911 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=e42ce0ce73ed280e43363b8b7766306fc64ad906;p=thirdparty%2Fvalgrind.git Generic fixes to iropt to enable it to be as sloppy with exceptions as we can get away with. git-svn-id: svn://svn.valgrind.org/vex/trunk@423 --- diff --git a/VEX/priv/guest-x86/ghelpers.c b/VEX/priv/guest-x86/ghelpers.c index 8ba9b31b3d..0a4d9f2904 100644 --- a/VEX/priv/guest-x86/ghelpers.c +++ b/VEX/priv/guest-x86/ghelpers.c @@ -1439,6 +1439,41 @@ static void dirtyhelper_CPUID ( VexGuestX86State* st ) } } +/*-----------------------------------------------------------*/ +/*--- Describing the x86 guest state, for the benefit ---*/ +/*--- of iropt and instrumenters. ---*/ +/*-----------------------------------------------------------*/ + +/* Figure out if any part of the guest state contained in minoff + .. maxoff requires precise memory exceptions. If in doubt return + True (but this is generates significantly slower code). + + We enforce precise exns for guest %ESP and %EIP only. +*/ +Bool guest_x86_state_requires_precise_mem_exns ( Int minoff, + Int maxoff) +{ + Int esp_min = offsetof(VexGuestX86State, guest_ESP); + Int esp_max = esp_min + 4 - 1; + Int eip_min = offsetof(VexGuestX86State, guest_EIP); + Int eip_max = eip_min + 4 - 1; + + if (maxoff < esp_min || minoff > esp_max) { + /* no overlap with esp */ + } else { + return True; + } + + if (maxoff < eip_min || minoff > eip_max) { + /* no overlap with eip */ + } else { + return True; + } + + return False; +} + + /*---------------------------------------------------------------*/ /*--- end guest-x86/ghelpers.c ---*/ /*---------------------------------------------------------------*/ diff --git a/VEX/priv/guest-x86/toIR.c b/VEX/priv/guest-x86/toIR.c index 41272fed8d..6da101ec2f 100644 --- a/VEX/priv/guest-x86/toIR.c +++ b/VEX/priv/guest-x86/toIR.c @@ -204,8 +204,6 @@ IRBB* bbToIR_X86Instr ( UChar* x86code, /*--- Offsets of various parts of the x86 guest state. ---*/ /*------------------------------------------------------------*/ -#define offsetof(type,memb) ((Int)&((type*)0)->memb) - #define OFFB_FPREGS offsetof(VexGuestX86State,guest_FPREG[0]) #define OFFB_FPTAGS offsetof(VexGuestX86State,guest_FPTAG[0]) #define OFFB_EAX offsetof(VexGuestX86State,guest_EAX) diff --git a/VEX/priv/ir/iropt.c b/VEX/priv/ir/iropt.c index ab478a0847..aa9e50fac3 100644 --- a/VEX/priv/ir/iropt.c +++ b/VEX/priv/ir/iropt.c @@ -1146,7 +1146,11 @@ static void redundant_get_removal_BB ( IRBB* bb ) overlapping ranges listed in env. Due to the flattening phase, the only stmt kind we expect to find a Get on is IRStmt_Tmp. */ -static void handle_gets_Stmt ( HashHW* env, IRStmt* st ) +static void handle_gets_Stmt ( + HashHW* env, + IRStmt* st, + Bool (*preciseMemExnsFn)(Int,Int) + ) { Int j; UInt key = 0; /* keep gcc -O happy */ @@ -1225,17 +1229,22 @@ static void handle_gets_Stmt ( HashHW* env, IRStmt* st ) be reordered with respect to memory references. That means at least the stack pointer. */ for (j = 0; j < env->used; j++) { -#if 0 - if (env->inuse[j] - && env->key[j] == (HWord)((16 << 16) | 19)) { - //vex_printf("found esp assignment\n"); + if (!env->inuse[j]) + continue; + if (vex_control.iropt_precise_memory_exns) { + /* Precise exceptions required. Flush all guest state. */ env->inuse[j] = False; - } -#else - env->inuse[j] = False; -#endif + } else { + /* Just flush the minimal amount required, as computed by + preciseMemExnsFn. */ + HWord k_lo = (env->key[j] >> 16) & 0xFFFF; + HWord k_hi = env->key[j] & 0xFFFF; + if (preciseMemExnsFn( k_lo, k_hi )) + env->inuse[j] = False; + } } - } + } /* if (memRW) */ + } @@ -1253,7 +1262,10 @@ static void handle_gets_Stmt ( HashHW* env, IRStmt* st ) overlapping (minoff,maxoff). */ -static void redundant_put_removal_BB ( IRBB* bb ) +static void redundant_put_removal_BB ( + IRBB* bb, + Bool (*preciseMemExnsFn)(Int,Int) + ) { Int i, j; Bool isPut; @@ -1320,7 +1332,7 @@ static void redundant_put_removal_BB ( IRBB* bb ) /* Deal with Gets. These remove bits of the environment since appearance of a Get means that the next event for that slice of the guest state is no longer a write, but a read. */ - handle_gets_Stmt( env, st ); + handle_gets_Stmt( env, st, preciseMemExnsFn ); } } @@ -3055,7 +3067,9 @@ static Bool iropt_verbose = False; //True; static IRBB* cheap_transformations ( IRBB* bb, - IRExpr* (*specHelper) ( Char*, IRExpr**) ) + IRExpr* (*specHelper) ( Char*, IRExpr**), + Bool (*preciseMemExnsFn)(Int,Int) + ) { redundant_get_removal_BB ( bb ); if (iropt_verbose) { @@ -3063,7 +3077,7 @@ IRBB* cheap_transformations ( ppIRBB(bb); } - redundant_put_removal_BB ( bb ); + redundant_put_removal_BB ( bb, preciseMemExnsFn ); if (iropt_verbose) { vex_printf("\n========= REDUNDANT PUT\n\n" ); ppIRBB(bb); @@ -3171,6 +3185,7 @@ static Bool hasGetIorPutI ( IRBB* bb ) IRBB* do_iropt_BB ( IRBB* bb0, IRExpr* (*specHelper) ( Char*, IRExpr**), + Bool (*preciseMemExnsFn)(Int,Int), Addr64 guest_addr ) { static UInt n_total = 0; @@ -3201,7 +3216,7 @@ IRBB* do_iropt_BB ( IRBB* bb0, If needed, do expensive transformations and then another cheap cleanup pass. */ - bb = cheap_transformations( bb, specHelper ); + bb = cheap_transformations( bb, specHelper, preciseMemExnsFn ); if (vex_control.iropt_level > 1) { do_expensive = hasGetIorPutI(bb); @@ -3211,7 +3226,7 @@ IRBB* do_iropt_BB ( IRBB* bb0, if (DEBUG_IROPT) vex_printf("***** EXPENSIVE %d %d\n", n_total, n_expensive); bb = expensive_transformations( bb ); - bb = cheap_transformations( bb, specHelper ); + bb = cheap_transformations( bb, specHelper, preciseMemExnsFn ); } /* Now have a go at unrolling simple (single-BB) loops. If @@ -3220,10 +3235,10 @@ IRBB* do_iropt_BB ( IRBB* bb0, bb2 = maybe_loop_unroll_BB( bb, guest_addr ); if (bb2) { show_res = False; //True; - bb = cheap_transformations( bb2, specHelper ); + bb = cheap_transformations( bb2, specHelper, preciseMemExnsFn ); if (do_expensive) { bb = expensive_transformations( bb ); - bb = cheap_transformations( bb, specHelper ); + bb = cheap_transformations( bb, specHelper, preciseMemExnsFn ); } else { /* at least do CSE and dead code removal */ cse_BB( bb ); diff --git a/VEX/priv/ir/iropt.h b/VEX/priv/ir/iropt.h index 9535541142..ec47b98063 100644 --- a/VEX/priv/ir/iropt.h +++ b/VEX/priv/ir/iropt.h @@ -13,6 +13,7 @@ extern IRBB* do_iropt_BB ( IRBB* bb, IRExpr* (*specHelper) ( Char*, IRExpr**), + Bool (*preciseMemExnsFn)(Int,Int), Addr64 guest_addr ); /*---------------------------------------------------------------*/ diff --git a/VEX/priv/main/vex_main.c b/VEX/priv/main/vex_main.c index e04247a5bc..878224bac9 100644 --- a/VEX/priv/main/vex_main.c +++ b/VEX/priv/main/vex_main.c @@ -7,6 +7,7 @@ /*---------------------------------------------------------------*/ #include "libvex.h" +#include "libvex_guest_x86.h" #include "main/vex_globals.h" #include "main/vex_util.h" @@ -151,6 +152,7 @@ TranslateResult LibVEX_Translate ( Int (*emit) ( UChar*, Int, HInstr* ); Addr64 (*findHelper) ( Char* ); IRExpr* (*specHelper) ( Char*, IRExpr** ); + Bool (*preciseMemExnsFn) ( Int, Int ); Bool host_is_bigendian = False; IRBB* irbb; @@ -173,6 +175,7 @@ TranslateResult LibVEX_Translate ( emit = NULL; findHelper = NULL; specHelper = NULL; + preciseMemExnsFn = NULL; saved_verbosity = vex_verbosity; if (bb_verbosity > 0) @@ -204,9 +207,10 @@ TranslateResult LibVEX_Translate ( switch (iset_guest) { case InsnSetX86: - bbToIR = bbToIR_X86Instr; - findHelper = x86guest_findhelper; - specHelper = x86guest_spechelper; + preciseMemExnsFn = guest_x86_state_requires_precise_mem_exns; + bbToIR = bbToIR_X86Instr; + findHelper = x86guest_findhelper; + specHelper = x86guest_spechelper; break; default: vpanic("LibVEX_Translate: unsupported guest insn set"); @@ -239,7 +243,8 @@ TranslateResult LibVEX_Translate ( sanityCheckIRBB(irbb, Ity_I32); /* Clean it up, hopefully a lot. */ - irbb = do_iropt_BB ( irbb, specHelper, guest_bytes_addr ); + irbb = do_iropt_BB ( irbb, specHelper, preciseMemExnsFn, + guest_bytes_addr ); sanityCheckIRBB(irbb, Ity_I32); if (vex_verbosity > 0) { diff --git a/VEX/pub/libvex_basictypes.h b/VEX/pub/libvex_basictypes.h index 25fa2ed873..b44e4a4a54 100644 --- a/VEX/pub/libvex_basictypes.h +++ b/VEX/pub/libvex_basictypes.h @@ -49,6 +49,10 @@ typedef ULong Addr64; typedef unsigned long HWord; +/* This is so useful it should be visible absolutely everywhere. */ +#define offsetof(type,memb) ((Int)&((type*)0)->memb) + + #endif /* ndef __LIBVEX_BASICTYPES_H */ diff --git a/VEX/pub/libvex_guest_x86.h b/VEX/pub/libvex_guest_x86.h index c534c7a8df..72a03e4e5f 100644 --- a/VEX/pub/libvex_guest_x86.h +++ b/VEX/pub/libvex_guest_x86.h @@ -106,10 +106,21 @@ typedef VexGuestX86State; +/* This is logically part of the guest state description. */ +/* Not visible to library client. */ +extern Bool guest_x86_state_requires_precise_mem_exns ( Int, Int ); + + + /*---------------------------------------------------------------*/ /*--- Utility functions for x86 guest stuff. ---*/ /*---------------------------------------------------------------*/ + + + +/* ALL THE FOLLOWING ARE VISIBLE TO LIBRARY CLIENT */ + /* Convert a saved x87 FPU image (as created by fsave) and write it into the supplied VexGuestX86State structure. The non-FP parts of said structure are left unchanged.