Author: sewardj
Date: Wed Jan 14 10:18:32 2015
New Revision: 14870
Log:
First running code for the NCode experiment -- infrastructure for
abstract machine code templates for inline instrumentation. Contains
initial implementation of Memcheck "LOADV64le" template, on amd64 only.
(Valgrind side)
Modified:
branches/NCODE/Makefile.all.am
branches/NCODE/Makefile.am
branches/NCODE/coregrind/m_translate.c
branches/NCODE/memcheck/mc_include.h
branches/NCODE/memcheck/mc_main.c
branches/NCODE/memcheck/mc_translate.c
Modified: branches/NCODE/Makefile.all.am
==============================================================================
--- branches/NCODE/Makefile.all.am (original)
+++ branches/NCODE/Makefile.all.am Wed Jan 14 10:18:32 2015
@@ -112,7 +112,7 @@
@FLAG_W_FORMAT_SECURITY@ \
@FLAG_FNO_STACK_PROTECTOR@ \
-fno-strict-aliasing \
- -fno-builtin
+ -fno-builtin -O -g
if COMPILER_IS_CLANG
AM_CFLAGS_BASE += -Wno-cast-align -Wno-self-assign \
Modified: branches/NCODE/Makefile.am
==============================================================================
--- branches/NCODE/Makefile.am (original)
+++ branches/NCODE/Makefile.am Wed Jan 14 10:18:32 2015
@@ -3,18 +3,20 @@
include $(top_srcdir)/Makefile.all.am
-TOOLS = memcheck \
- cachegrind \
- callgrind \
- massif \
- lackey \
- none \
- helgrind \
- drd
-
-EXP_TOOLS = exp-sgcheck \
- exp-bbv \
- exp-dhat
+#TOOLS = memcheck \
+# cachegrind \
+# callgrind \
+# massif \
+# lackey \
+# none \
+# helgrind \
+# drd
+#
+#EXP_TOOLS = exp-sgcheck \
+# exp-bbv \
+# exp-dhat
+TOOLS = none memcheck
+EXP_TOOLS =
# Put docs last because building the HTML is slow and we want to get
# everything else working before we try it.
Modified: branches/NCODE/coregrind/m_translate.c
==============================================================================
--- branches/NCODE/coregrind/m_translate.c (original)
+++ branches/NCODE/coregrind/m_translate.c Wed Jan 14 10:18:32 2015
@@ -1664,19 +1664,19 @@
hassle, because we don't expect them to get used often. So
don't bother. */
if (allow_redirection) {
- vta.disp_cp_chain_me_to_slowEP
+ vta.vda.disp_cp_chain_me_to_slowEP
= VG_(fnptr_to_fnentry)( &VG_(disp_cp_chain_me_to_slowEP) );
- vta.disp_cp_chain_me_to_fastEP
+ vta.vda.disp_cp_chain_me_to_fastEP
= VG_(fnptr_to_fnentry)( &VG_(disp_cp_chain_me_to_fastEP) );
- vta.disp_cp_xindir
+ vta.vda.disp_cp_xindir
= VG_(fnptr_to_fnentry)( &VG_(disp_cp_xindir) );
} else {
- vta.disp_cp_chain_me_to_slowEP = NULL;
- vta.disp_cp_chain_me_to_fastEP = NULL;
- vta.disp_cp_xindir = NULL;
+ vta.vda.disp_cp_chain_me_to_slowEP = NULL;
+ vta.vda.disp_cp_chain_me_to_fastEP = NULL;
+ vta.vda.disp_cp_xindir = NULL;
}
/* This doesn't involve chaining and so is always allowable. */
- vta.disp_cp_xassisted
+ vta.vda.disp_cp_xassisted
= VG_(fnptr_to_fnentry)( &VG_(disp_cp_xassisted) );
/* Sheesh. Finally, actually _do_ the translation! */
Modified: branches/NCODE/memcheck/mc_include.h
==============================================================================
--- branches/NCODE/memcheck/mc_include.h (original)
+++ branches/NCODE/memcheck/mc_include.h Wed Jan 14 10:18:32 2015
@@ -596,7 +596,14 @@
/*--- Instrumentation ---*/
/*------------------------------------------------------------*/
-/* Functions defined in mc_main.c */
+/* NCode templates and template generators, defined in mc_main.c */
+
+void MC_(create_ncode_templates) ( void );
+
+extern NCodeTemplate* MC_(tmpl__LOADV64le_on_64);
+
+
+/* Helper functions defined in mc_main.c */
/* For the fail_w_o functions, the UWord arg is actually the 32-bit
origin tag and should really be UInt, but to be simple and safe
Modified: branches/NCODE/memcheck/mc_main.c
==============================================================================
--- branches/NCODE/memcheck/mc_main.c (original)
+++ branches/NCODE/memcheck/mc_main.c Wed Jan 14 10:18:32 2015
@@ -4192,21 +4192,9 @@
/*------------------------------------------------------------*/
-/*--- Functions called directly from generated code: ---*/
-/*--- Load/store handlers. ---*/
+/*--- Definition of MASK ---*/
/*------------------------------------------------------------*/
-/* Types: LOADV32, LOADV16, LOADV8 are:
- UWord fn ( Addr a )
- so they return 32-bits on 32-bit machines and 64-bits on
- 64-bit machines. Addr has the same size as a host word.
-
- LOADV64 is always ULong fn ( Addr a )
-
- Similarly for STOREV8, STOREV16, STOREV32, the supplied vbits
- are a UWord, and for STOREV64 they are a ULong.
-*/
-
/* If any part of '_a' indicated by the mask is 1, either '_a' is not
naturally '_sz/8'-aligned, or it exceeds the range covered by the
primary map. This is all very tricky (and important!), so let's
@@ -4282,6 +4270,92 @@
*/
+/*------------------------------------------------------------*/
+/*--- Creating NCode templates ---*/
+/*------------------------------------------------------------*/
+
+static ULong mc_LOADV64le_slow ( Addr a );
+
+static void* ncode_alloc ( UInt n ) {
+ return VG_(malloc)("mc.ncode_alloc (NCode, permanent)", n);
+}
+
+static NReg mkNRegINVALID ( void ) {
+ return mkNReg(Nrr_INVALID, 0);
+}
+
+static NReg* mkNRegVec1 ( NAlloc na, NReg r0 ) {
+ NReg* vec = na(2 * sizeof(NReg));
+ vec[0] = r0;
+ vec[1] = mkNRegINVALID();
+ return vec;
+}
+
+NCodeTemplate* MC_(tmpl__LOADV64le_on_64) = NULL;
+
+static NCodeTemplate* mk_tmpl__LOADV64le_on_64 ( NAlloc na )
+{
+ NInstr** hot = na((11+1) * sizeof(NInstr*));
+ NInstr** cold = na((6+1) * sizeof(NInstr*));
+
+ NReg rINVALID = mkNRegINVALID();
+
+ NReg r0 = mkNReg(Nrr_Result, 0);
+ NReg a0 = mkNReg(Nrr_Argument, 0);
+ NReg s0 = mkNReg(Nrr_Scratch, 0);
+
+ hot[0] = NInstr_SetFlagsWri (na, Nsf_TEST, a0, MASK(8));
+ hot[1] = NInstr_Branch (na, Ncc_NZ, mkNLabel(Nlz_Cold, 4));
+ hot[2] = NInstr_ShiftWri (na, Nsh_SHR, s0, a0, 16);
+ hot[3] = NInstr_LoadU (na, s0, NEA_IRS(na, (HWord)&primary_map[0],
+ s0, 3), 8);
+ hot[4] = NInstr_AluWri (na, Nalu_AND, r0, a0, 0xFFFF);
+ hot[5] = NInstr_ShiftWri (na, Nsh_SHR, r0, r0, 3);
+ hot[6] = NInstr_LoadU (na, r0, NEA_RRS(na, s0, r0, 1), 2);
+ hot[7] = NInstr_SetFlagsWri (na, Nsf_CMP, r0, VA_BITS16_DEFINED);
+ hot[8] = NInstr_Branch (na, Ncc_NZ, mkNLabel(Nlz_Cold, 0));
+ hot[9] = NInstr_ImmW (na, r0, V_BITS64_DEFINED);
+ hot[10] = NInstr_Nop (na);
+
+ cold[0] = NInstr_MovW (na, s0, r0);
+ cold[1] = NInstr_ImmW (na, r0, V_BITS64_UNDEFINED);
+ cold[2] = NInstr_SetFlagsWri (na, Nsf_CMP, s0, VA_BITS16_UNDEFINED);
+ cold[3] = NInstr_Branch (na, Ncc_Z, mkNLabel(Nlz_Hot, 10));
+ cold[4] = NInstr_Call (na, rINVALID, r0, mkNRegVec1(na, a0),
+ (void*)& mc_LOADV64le_slow,
+ "mc_LOADV64le_slow");
+ cold[5] = NInstr_Branch(na, Ncc_ALWAYS, mkNLabel(Nlz_Hot, 10));
+
+ hot[11] = cold[6] = NULL;
+ NCodeTemplate* tmpl
+ = mkNCodeTemplate(na,"LOADV64le_on_64",
+ /*res, parms, scratch*/1, 1, 1, hot, cold);
+ return tmpl;
+}
+
+void MC_(create_ncode_templates) ( void )
+{
+ tl_assert(MC_(tmpl__LOADV64le_on_64) == NULL);
+ MC_(tmpl__LOADV64le_on_64) = mk_tmpl__LOADV64le_on_64(ncode_alloc);
+}
+
+
+/*------------------------------------------------------------*/
+/*--- Functions called directly from generated code: ---*/
+/*--- Load/store handlers. ---*/
+/*------------------------------------------------------------*/
+
+/* Types: LOADV32, LOADV16, LOADV8 are:
+ UWord fn ( Addr a )
+ so they return 32-bits on 32-bit machines and 64-bits on
+ 64-bit machines. Addr has the same size as a host word.
+
+ LOADV64 is always ULong fn ( Addr a )
+
+ Similarly for STOREV8, STOREV16, STOREV32, the supplied vbits
+ are a UWord, and for STOREV64 they are a ULong.
+*/
+
/* ------------------------ Size = 16 ------------------------ */
static INLINE
@@ -4398,6 +4472,10 @@
return mc_LOADV64(a, False);
}
+static ULong mc_LOADV64le_slow ( Addr a )
+{
+ return mc_LOADVn_slow( a, 64, False/*!isBigEndian*/ );
+}
static INLINE
void mc_STOREV64 ( Addr a, ULong vbits64, Bool isBigEndian )
@@ -6660,6 +6738,12 @@
/* Do not check definedness of guest state if --undef-value-errors=no */
if (MC_(clo_mc_level) >= 2)
VG_(track_pre_reg_read) ( mc_pre_reg_read );
+
+ /* The NCode templates also need to be created, but this is done
+ later, at the first call to MC_(instrument), so as to allow VEX
+ to more be more fully initialised. In particular, at this
+ point, we can create the templates, but we can't yet print them,
+ which is inconvenient for debugging. Create them later on. */
}
static void print_SM_info(const HChar* type, Int n_SMs)
Modified: branches/NCODE/memcheck/mc_translate.c
==============================================================================
--- branches/NCODE/memcheck/mc_translate.c (original)
+++ branches/NCODE/memcheck/mc_translate.c Wed Jan 14 10:18:32 2015
@@ -4582,9 +4582,39 @@
the address (shadow) to 'defined' following the test. */
complainIfUndefined( mce, addr, guard );
+ /* Generate the actual address into addrAct. */
+ IRAtom* addrAct;
+ if (bias == 0) {
+ addrAct = addr;
+ } else {
+ IROp mkAdd;
+ IRAtom* eBias;
+ IRType tyAddr = mce->hWordTy;
+ tl_assert( tyAddr == Ity_I32 || tyAddr == Ity_I64 );
+ mkAdd = tyAddr==Ity_I32 ? Iop_Add32 : Iop_Add64;
+ eBias = tyAddr==Ity_I32 ? mkU32(bias) : mkU64(bias);
+ addrAct = assignNew('V', mce, tyAddr, binop(mkAdd, addr, eBias) );
+ }
+
+ /* We need to have a place to park the V bits we're just about to
+ read. */
+ ty = shadowTypeV(ty);
+ IRTemp datavbits = newTemp(mce, ty, VSh);
+
+ /* ------ BEGIN inline NCode ? ------ */
+ if (guard == NULL
+ && end == Iend_LE && ty == Ity_I64 && mce->hWordTy == Ity_I64) {
+ /* Unconditional LOAD64le on 64 bit host. Generate inline code. */
+ NCodeTemplate* tmpl = MC_(tmpl__LOADV64le_on_64);
+ IRAtom** args = mkIRExprVec_1( addrAct );
+ IRTemp* ress = mkIRTempVec_1( datavbits );
+ stmt( 'V', mce, IRStmt_NCode(tmpl, args, ress) );
+ return mkexpr(datavbits);
+ }
+ /* ------ END inline NCode ? ------ */
+
/* Now cook up a call to the relevant helper function, to read the
data V bits from shadow memory. */
- ty = shadowTypeV(ty);
void* helper = NULL;
const HChar* hname = NULL;
@@ -4645,24 +4675,6 @@
tl_assert(helper);
tl_assert(hname);
- /* Generate the actual address into addrAct. */
- IRAtom* addrAct;
- if (bias == 0) {
- addrAct = addr;
- } else {
- IROp mkAdd;
- IRAtom* eBias;
- IRType tyAddr = mce->hWordTy;
- tl_assert( tyAddr == Ity_I32 || tyAddr == Ity_I64 );
- mkAdd = tyAddr==Ity_I32 ? Iop_Add32 : Iop_Add64;
- eBias = tyAddr==Ity_I32 ? mkU32(bias) : mkU64(bias);
- addrAct = assignNew('V', mce, tyAddr, binop(mkAdd, addr, eBias) );
- }
-
- /* We need to have a place to park the V bits we're just about to
- read. */
- IRTemp datavbits = newTemp(mce, ty, VSh);
-
/* Here's the call. */
IRDirty* di;
if (ret_via_outparam) {
@@ -6226,6 +6238,13 @@
tl_assert(MC_(clo_mc_level) >= 1 && MC_(clo_mc_level) <= 3);
+ /* If this is the first call, set up the NCode templates. */
+ static Bool ncode_templates_created = False;
+ if (!ncode_templates_created) {
+ ncode_templates_created = True;
+ MC_(create_ncode_templates)();
+ }
+
/* Set up SB */
sb_out = deepCopyIRSBExceptStmts(sb_in);
|