extern
Bool guest_x86_state_requires_precise_mem_exns ( Int, Int );
+extern
+VexGuestLayoutInfo x86guest_layout;
+
/*---------------------------------------------------------*/
/*--- Condition code stuff ---*/
#include "libvex_basictypes.h"
#include "libvex_guest_x86.h"
#include "libvex_ir.h"
+#include "libvex.h"
#include "main/vex_util.h"
#include "guest-x86/gdefs.h"
}
+VexGuestLayoutInfo
+ x86guest_layout
+ = { .offset_SP = offsetof(VexGuestX86State, guest_ESP),
+ .sizeof_SP = 4 };
+
+
/*---------------------------------------------------------------*/
/*--- end guest-x86/ghelpers.c ---*/
/*---------------------------------------------------------------*/
if (d->needsBBP)
vex_printf(" NeedsBBP");
if (d->mFx != Ifx_None) {
+ vex_printf(" ");
ppIREffect(d->mFx);
vex_printf("-mem(");
ppIRExpr(d->mAddr);
- vex_printf(",%d) ", d->mSize);
+ vex_printf(",%d)", d->mSize);
}
for (i = 0; i < d->nFxState; i++) {
+ vex_printf(" ");
ppIREffect(d->fxState[i].fx);
- vex_printf("-gst(%d,%d) ", d->fxState[i].offset, d->fxState[i].size);
+ vex_printf("-gst(%d,%d)", d->fxState[i].offset, d->fxState[i].size);
}
vex_printf(" ::: ");
if (d->tmp != INVALID_IRTEMP) {
case Ity_I8: return 1;
case Ity_I16: return 2;
case Ity_I32: return 4;
+ case Ity_I64: return 8;
+ case Ity_F32: return 4;
case Ity_F64: return 8;
default: vex_printf("\n"); ppIRType(ty); vex_printf("\n");
vpanic("sizeofIRType");
}
}
+IRExpr* mkIRExpr_HWord ( HWord hw )
+{
+ if (sizeof(HWord) == 4)
+ return IRExpr_Const(IRConst_U32((UInt)hw));
+ if (sizeof(HWord) == 8)
+ return IRExpr_Const(IRConst_U64((Long)hw));
+ vpanic("mkIRExpr_HWord");
+}
/*---------------------------------------------------------------*/
/*--- end ir/irdefs.c ---*/
/*--- Flattening out a BB into pure SSA form ---*/
/*---------------------------------------------------------------*/
-inline
-static Bool isAtom ( IRExpr* e )
-{
- return e->tag == Iex_Tmp || e->tag == Iex_Const;
-}
-
-
/* Non-critical helper, heuristic for reducing the number of tmp-tmp
copies made by flattening. If in doubt return False. */
IRDirty *d, *d2;
switch (st->tag) {
case Ist_Put:
- e1 = flatten_Expr(bb, st->Ist.Put.data);
- addStmtToIRBB(bb, IRStmt_Put(st->Ist.Put.offset, e1));
+ if (isAtom(st->Ist.Put.data)) {
+ /* optimisation to reduce the amount of heap wasted
+ by the flattener */
+ addStmtToIRBB(bb, st);
+ } else {
+ /* general case, always correct */
+ e1 = flatten_Expr(bb, st->Ist.Put.data);
+ addStmtToIRBB(bb, IRStmt_Put(st->Ist.Put.offset, e1));
+ }
break;
case Ist_PutI:
e1 = flatten_Expr(bb, st->Ist.PutI.off);
E', delete the binding if it is not used. Otherwise, add any temp
uses to the set and keep on moving backwards. */
-static void dead_BB ( IRBB* bb )
+/* notstatic */ void do_deadcode_BB ( IRBB* bb )
{
Int i;
Int n_tmps = bb->tyenv->types_used;
-static void treebuild_BB ( IRBB* bb )
+/* notstatic */ void do_treebuild_BB ( IRBB* bb )
{
Int i, j, k;
Bool invPut, invStore;
ppIRBB(bb);
}
- dead_BB ( bb );
+ do_deadcode_BB ( bb );
if (iropt_verbose) {
vex_printf("\n========= DEAD\n\n" );
ppIRBB(bb);
}
spec_helpers_BB ( bb, specHelper );
- dead_BB ( bb );
+ do_deadcode_BB ( bb );
if (iropt_verbose) {
vex_printf("\n========= SPECd \n\n" );
ppIRBB(bb);
collapse_AddSub_chains_BB( bb );
do_PutI_GetI_forwarding_BB( bb );
do_redundant_PutI_elimination( bb );
- dead_BB( bb );
+ do_deadcode_BB( bb );
return flatten_BB( bb );
}
} else {
/* at least do CSE and dead code removal */
cse_BB( bb );
- dead_BB( bb );
+ do_deadcode_BB( bb );
}
if (0) vex_printf("vex iropt: unrolled a loop\n");
}
}
- /* Finally, rebuild trees, for the benefit of instruction
- selection. */
- dead_BB(bb);
- treebuild_BB( bb );
- if (show_res || iropt_verbose) {
- vex_printf("\n========= TREEd \n\n" );
- ppIRBB(bb);
- }
-
+ /* sigh; flatten the block out (yet again) for the benefit of
+ instrumenters. */
+ bb = flatten_BB( bb );
return bb;
}
#include "libvex_ir.h"
#include "libvex.h"
+/* Top level optimiser entry point. Returns a new BB. Operates
+ under the control of the global "vex_control" struct. */
+extern
+IRBB* do_iropt_BB ( IRBB* bb,
+ IRExpr* (*specHelper) ( Char*, IRExpr**),
+ Bool (*preciseMemExnsFn)(Int,Int),
+ Addr64 guest_addr );
-extern IRBB* do_iropt_BB ( IRBB* bb,
- IRExpr* (*specHelper) ( Char*, IRExpr**),
- Bool (*preciseMemExnsFn)(Int,Int),
- Addr64 guest_addr );
+/* Do a dead-code removal pass, which is generally needed to avoid
+ crashing the tree-builder. bb is destructively modified. */
+extern
+void do_deadcode_BB ( IRBB* bb );
+
+/* The tree-builder. Make maximal safe trees. bb is destructively
+ modified. */
+extern
+void do_treebuild_BB ( IRBB* bb );
/*---------------------------------------------------------------*/
/*--- end ir/iropt.h ---*/
Int host_bytes_size,
/* OUT: how much of the output area is used. */
Int* host_bytes_used,
- /* IN: optionally, an instrumentation function. */
- IRBB* (*instrument) ( IRBB* ),
+ /* IN: optionally, two instrumentation functions. */
+ IRBB* (*instrument1) ( IRBB*, VexGuestLayoutInfo* ),
+ IRBB* (*instrument2) ( IRBB*, VexGuestLayoutInfo* ),
HWord (*tool_findhelper) ( Char* ),
/* IN: optionally, an access check function for guest code. */
Bool (*byte_accessible) ( Addr64 ),
IRExpr* (*specHelper) ( Char*, IRExpr** );
Bool (*preciseMemExnsFn) ( Int, Int );
- Bool host_is_bigendian = False;
- IRBB* irbb;
- HInstrArray* vcode;
- HInstrArray* rcode;
- Int i, j, k, out_used, saved_verbosity, guest_sizeB;
- UChar insn_bytes[32];
- IRType guest_word_size;
+ VexGuestLayoutInfo* guest_layout;
+ Bool host_is_bigendian = False;
+ IRBB* irbb;
+ HInstrArray* vcode;
+ HInstrArray* rcode;
+ Int i, j, k, out_used, saved_verbosity, guest_sizeB;
+ UChar insn_bytes[32];
+ IRType guest_word_size;
+ guest_layout = NULL;
available_real_regs = NULL;
n_available_real_regs = 0;
isMove = NULL;
specHelper = x86guest_spechelper;
guest_sizeB = sizeof(VexGuestX86State);
guest_word_size = Ity_I32;
+ guest_layout = &x86guest_layout;
break;
default:
vpanic("LibVEX_Translate: unsupported guest insn set");
}
/* Get the thing instrumented. */
- if (instrument) {
- irbb = (*instrument)(irbb);
+ if (instrument1)
+ irbb = (*instrument1)(irbb, guest_layout);
+ if (instrument2)
+ irbb = (*instrument2)(irbb, guest_layout);
+
+ if (instrument1 || instrument2)
sanityCheckIRBB(irbb, guest_word_size);
- }
/* Turn it into virtual-registerised code. */
+ do_deadcode_BB( irbb );
+ do_treebuild_BB( irbb );
vcode = iselBB ( irbb, findHelper, tool_findhelper );
if (vex_verbosity > 0) {
extern void* LibVEX_Alloc ( Int nbytes );
+/* Describe the guest state enough that the instrumentation
+ functions can work. */
+
+typedef
+ struct {
+ /* Whereabouts is the stack pointer? */
+ Int offset_SP;
+ Int sizeof_SP; /* 4 or 8 */
+ }
+ VexGuestLayoutInfo;
+
+
/* Translate a basic block. */
typedef
Int host_bytes_size,
/* OUT: how much of the output area is used. */
Int* host_bytes_used,
- /* IN: optionally, an instrumentation function. */
- IRBB* (*instrument) ( IRBB* ),
+ /* IN: optionally, two instrumentation functions. */
+ IRBB* (*instrument1) ( IRBB*, VexGuestLayoutInfo* ),
+ IRBB* (*instrument2) ( IRBB*, VexGuestLayoutInfo* ),
HWord (*tool_findhelper) ( Char* ),
/* IN: optionally, an access check function for guest code. */
Bool (*byte_accessible) ( Addr64 ),
extern IRExpr** sopyIRExprVec ( IRExpr** );
extern IRExpr** dopyIRExprVec ( IRExpr** );
+/* Make a constant expression from the given host word,
+ taking into account of course the host word size. */
+extern IRExpr* mkIRExpr_HWord ( HWord );
+
+
+inline static Bool isAtom ( IRExpr* e ) {
+ return e->tag == Iex_Tmp || e->tag == Iex_Const;
+}
+
/* ------------------ Dirty helper calls ------------------ */