Add a mini-version of the addrcheck instrumenter so as to help refine
the reg-allocator in the presence of lots of helper calls.
git-svn-id: svn://svn.valgrind.org/vex/trunk@466 8f6e269a-dfd6-0310-a8e1-e2731360e62c
diff --git a/test_main.c b/test_main.c
index 50372ca..6eab8b1 100644
--- a/test_main.c
+++ b/test_main.c
@@ -9,6 +9,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
+#include <string.h>
#include "libvex_basictypes.h"
#include "libvex.h"
@@ -46,6 +47,10 @@
static Bool verbose = True;
+/* Forwards */
+static IRBB* ac_instrument ( IRBB*, VexGuestLayoutInfo* );
+
+
int main ( int argc, char** argv )
{
FILE* f;
@@ -116,9 +121,8 @@
InsnSetX86, InsnSetX86,
origbuf, (Addr64)orig_addr, &orig_used,
transbuf, N_TRANSBUF, &trans_used,
- NULL, /* instrument1 */
+ ac_instrument, //NULL, /* instrument1 */
NULL, /* instrument2 */
- NULL, /* tool-findhelper */
NULL, /* access checker */
TEST_FLAGS
);
@@ -140,3 +144,145 @@
return 0;
}
+
+//////////////////////////////////////////////////////////////////////
+
+static
+void panic ( Char* s )
+{
+ printf("\npanic: %s\n", s);
+ failure_exit();
+}
+
+static
+IRBB* ac_instrument (IRBB* bb_in, VexGuestLayoutInfo* layout)
+{
+/* Use this rather than eg. -1 because it's a UInt. */
+#define INVALID_DATA_SIZE 999999
+
+ Int i;
+ Int sz;
+ IRCallee* helper;
+ IRStmt* st;
+ IRExpr* data;
+ IRExpr* addr;
+ Bool needSz;
+
+ /* Set up BB */
+ IRBB* bb = emptyIRBB();
+ bb->tyenv = dopyIRTypeEnv(bb_in->tyenv);
+ bb->next = dopyIRExpr(bb_in->next);
+ bb->jumpkind = bb_in->jumpkind;
+
+ /* No loads to consider in ->next. */
+ assert(isAtom(bb_in->next));
+
+ for (i = 0; i < bb_in->stmts_used; i++) {
+ st = bb_in->stmts[i];
+ if (!st) continue;
+
+ switch (st->tag) {
+
+ case Ist_Tmp:
+ data = st->Ist.Tmp.data;
+ if (data->tag == Iex_LDle) {
+ addr = data->Iex.LDle.addr;
+ sz = sizeofIRType(data->Iex.LDle.ty);
+ needSz = False;
+ switch (sz) {
+ case 4: helper = mkIRCallee(1, "ac_helperc_LOAD4",
+ 0x12345601); break;
+ case 2: helper = mkIRCallee(0, "ac_helperc_LOAD2",
+ 0x12345602); break;
+ case 1: helper = mkIRCallee(1, "ac_helperc_LOAD1",
+ 0x12345603); break;
+ default: helper = mkIRCallee(0, "ac_helperc_LOADN",
+ 0x12345604);
+ needSz = True; break;
+ }
+ if (needSz) {
+ addStmtToIRBB(
+ bb,
+ IRStmt_Dirty(
+ unsafeIRDirty_0_N( helper,
+ mkIRExprVec_2(addr, mkIRExpr_HWord(sz)))
+ ));
+ } else {
+ addStmtToIRBB(
+ bb,
+ IRStmt_Dirty(
+ unsafeIRDirty_0_N( helper,
+ mkIRExprVec_1(addr) )
+ ));
+ }
+ }
+ break;
+
+ case Ist_STle:
+ data = st->Ist.STle.data;
+ addr = st->Ist.STle.addr;
+ assert(isAtom(data));
+ assert(isAtom(addr));
+ sz = sizeofIRType(typeOfIRExpr(bb_in->tyenv, data));
+ needSz = False;
+ switch (sz) {
+ case 4: helper = mkIRCallee(1, "ac_helperc_STORE4",
+ 0x12345605); break;
+ case 2: helper = mkIRCallee(0, "ac_helperc_STORE2",
+ 0x12345606); break;
+ case 1: helper = mkIRCallee(1, "ac_helperc_STORE1",
+ 0x12345607); break;
+ default: helper = mkIRCallee(0, "ac_helperc_STOREN",
+ 0x12345608);
+ needSz = True; break;
+ }
+ if (needSz) {
+ addStmtToIRBB(
+ bb,
+ IRStmt_Dirty(
+ unsafeIRDirty_0_N( helper,
+ mkIRExprVec_2(addr, mkIRExpr_HWord(sz)))
+ ));
+ } else {
+ addStmtToIRBB(
+ bb,
+ IRStmt_Dirty(
+ unsafeIRDirty_0_N( helper,
+ mkIRExprVec_1(addr) )
+ ));
+ }
+ break;
+
+ case Ist_Put:
+ assert(isAtom(st->Ist.Put.data));
+ break;
+
+ case Ist_PutI:
+ assert(isAtom(st->Ist.PutI.off));
+ assert(isAtom(st->Ist.PutI.data));
+ break;
+
+ case Ist_Exit:
+ assert(isAtom(st->Ist.Exit.cond));
+ break;
+
+ case Ist_Dirty:
+ /* If the call doesn't interact with memory, we ain't
+ interested. */
+ if (st->Ist.Dirty.details->mFx == Ifx_None)
+ break;
+ goto unhandled;
+
+ default:
+ unhandled:
+ printf("\n");
+ ppIRStmt(st);
+ printf("\n");
+ panic("addrcheck: unhandled IRStmt");
+ }
+
+ addStmtToIRBB( bb, dopyIRStmt(st));
+ }
+
+ return bb;
+}