From: Julian Seward Date: Sat, 30 Oct 2004 19:03:02 +0000 (+0000) Subject: Instead of denoting helper call targets by their names, add a new type X-Git-Tag: svn/VALGRIND_3_0_1^2~873 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=6fda2b6b3cb67e06196bc8061f0688c4356d7723;p=thirdparty%2Fvalgrind.git Instead of denoting helper call targets by their names, add a new type IRCallee to carry the name (for printing), the actual address, and the "regparm" number if relevant. This gets rid of the need to pass around helper-lookup callbacks all over the place, and also lays the groundwork for a generic "regparm" mechanism for the back end. git-svn-id: svn://svn.valgrind.org/vex/trunk@461 --- diff --git a/VEX/priv/guest-x86/gdefs.h b/VEX/priv/guest-x86/gdefs.h index ab43597f69..f4d714933f 100644 --- a/VEX/priv/guest-x86/gdefs.h +++ b/VEX/priv/guest-x86/gdefs.h @@ -26,11 +26,6 @@ IRBB* bbToIR_X86Instr ( UChar* x86code, Bool (*byte_accessible)(Addr64), Bool host_bigendian ); -/* Used by the back end to look up addresses of helper - function calls inserted by bbToIR_X86Instr. */ -extern -HWord x86guest_findhelper ( Char* function_name ); - /* Used by the optimiser to specialise calls to helpers. */ extern IRExpr* x86guest_spechelper ( Char* function_name, @@ -46,6 +41,24 @@ extern VexGuestLayoutInfo x86guest_layout; +/*---------------------------------------------------------*/ +/*--- x86 guest helpers ---*/ +/*---------------------------------------------------------*/ + +/* --- CLEAN HELPERS --- */ +extern UInt calculate_eflags_all ( UInt cc_op, UInt cc_src, UInt cc_dst ); +extern UInt calculate_eflags_c ( UInt cc_op, UInt cc_src, UInt cc_dst ); +extern UInt calculate_condition ( UInt/*Condcode*/ cond, + UInt cc_op, UInt cc_src, UInt cc_dst ); +extern UInt calculate_FXAM ( UInt tag, ULong dbl ); +extern ULong calculate_RCR ( UInt arg, UInt rot_amt, UInt eflags_in, UInt sz ); + +/* --- DIRTY HELPERS --- */ +extern ULong loadF80le ( UInt ); +extern void storeF80le ( UInt, ULong ); +extern void dirtyhelper_CPUID ( VexGuestX86State* ); + + /*---------------------------------------------------------*/ /*--- Condition code stuff ---*/ /*---------------------------------------------------------*/ diff --git a/VEX/priv/guest-x86/ghelpers.c b/VEX/priv/guest-x86/ghelpers.c index b564bab353..50dea82418 100644 --- a/VEX/priv/guest-x86/ghelpers.c +++ b/VEX/priv/guest-x86/ghelpers.c @@ -14,21 +14,6 @@ #include "main/vex_util.h" #include "guest-x86/gdefs.h" -/* --- Forwardses --- */ - -/* --- CLEAN HELPERS --- */ -static UInt calculate_eflags_all ( UInt cc_op, UInt cc_src, UInt cc_dst ); -static UInt calculate_eflags_c ( UInt cc_op, UInt cc_src, UInt cc_dst ); -static UInt calculate_condition ( UInt/*Condcode*/ cond, - UInt cc_op, UInt cc_src, UInt cc_dst ); -static UInt calculate_FXAM ( UInt tag, ULong dbl ); -static ULong calculate_RCR ( UInt arg, UInt rot_amt, UInt eflags_in, UInt sz ); - -/* --- DIRTY HELPERS --- */ -static ULong loadF80le ( UInt ); -static void storeF80le ( UInt, ULong ); -static void dirtyhelper_CPUID ( VexGuestX86State* ); - /* This file contains helper functions for x86 guest code. Calls to these functions are generated by the back end. @@ -413,7 +398,6 @@ static void initCounts ( void ) /* CALLED FROM GENERATED CODE: CLEAN HELPER */ /* Calculate all the 6 flags from the supplied thunk parameters. */ -static UInt calculate_eflags_all ( UInt cc_op, UInt cc_src_formal, UInt cc_dst_formal ) { # if PROFILE_EFLAGS @@ -488,7 +472,7 @@ UInt calculate_eflags_all ( UInt cc_op, UInt cc_src_formal, UInt cc_dst_formal ) /* CALLED FROM GENERATED CODE: CLEAN HELPER */ /* Calculate just the carry flag from the supplied thunk parameters. */ -static UInt calculate_eflags_c ( UInt cc_op, UInt cc_src, UInt cc_dst ) +UInt calculate_eflags_c ( UInt cc_op, UInt cc_src, UInt cc_dst ) { /* Fast-case some common ones. */ switch (cc_op) { @@ -597,27 +581,6 @@ static UInt calculate_eflags_c ( UInt cc_op, UInt cc_src, UInt cc_dst ) } -HWord x86guest_findhelper ( Char* function_name ) -{ - if (vex_streq(function_name, "calculate_condition")) - return (HWord)(& calculate_condition); - if (vex_streq(function_name, "calculate_eflags_c")) - return (HWord)(& calculate_eflags_c); - if (vex_streq(function_name, "calculate_eflags_all")) - return (HWord)(& calculate_eflags_all); - if (vex_streq(function_name, "calculate_FXAM")) - return (HWord)(& calculate_FXAM); - if (vex_streq(function_name, "storeF80le")) - return (HWord)(& storeF80le); - if (vex_streq(function_name, "loadF80le")) - return (HWord)(& loadF80le); - if (vex_streq(function_name, "calculate_RCR")) - return (HWord)(& calculate_RCR); - if (vex_streq(function_name, "dirtyhelper_CPUID")) - return (HWord)(& dirtyhelper_CPUID); - return 0; /* not found */ -} - /* Used by the optimiser to try specialisations. Returns an equivalent expression, or NULL if none. */ @@ -858,7 +821,7 @@ static inline Bool host_is_little_endian ( void ) } /* CALLED FROM GENERATED CODE: CLEAN HELPER */ -static UInt calculate_FXAM ( UInt tag, ULong dbl ) +UInt calculate_FXAM ( UInt tag, ULong dbl ) { Bool mantissaIsZero; Int bexp; @@ -1192,7 +1155,7 @@ static void convert_f80le_to_f64le ( /*IN*/UChar* f80, /*OUT*/UChar* f64 ) /* CALLED FROM GENERATED CODE */ /* DIRTY HELPER (reads guest memory) */ -static ULong loadF80le ( UInt addrU ) +ULong loadF80le ( UInt addrU ) { ULong f64; convert_f80le_to_f64le ( (UChar*)addrU, (UChar*)&f64 ); @@ -1201,7 +1164,7 @@ static ULong loadF80le ( UInt addrU ) /* CALLED FROM GENERATED CODE */ /* DIRTY HELPER (writes guest memory) */ -static void storeF80le ( UInt addrU, ULong f64 ) +void storeF80le ( UInt addrU, ULong f64 ) { convert_f64le_to_f80le( (UChar*)&f64, (UChar*)addrU ); } @@ -1393,7 +1356,7 @@ void LibVEX_GuestX86_initialise ( /*OUT*/VexGuestX86State* vex_state ) through the carry bit. Result in low 32 bits, new flags (OSZACP) in high 32 bits. */ -static ULong calculate_RCR ( UInt arg, UInt rot_amt, UInt eflags_in, UInt sz ) +ULong calculate_RCR ( UInt arg, UInt rot_amt, UInt eflags_in, UInt sz ) { UInt tempCOUNT = rot_amt & 0x1F, cf=0, of=0, tempcf; @@ -1446,7 +1409,7 @@ static ULong calculate_RCR ( UInt arg, UInt rot_amt, UInt eflags_in, UInt sz ) /* CALLED FROM GENERATED CODE */ /* DIRTY HELPER (modifies guest state) */ /* Claim to be a P54C P133 (pre-MMX Pentium) */ -static void dirtyhelper_CPUID ( VexGuestX86State* st ) +void dirtyhelper_CPUID ( VexGuestX86State* st ) { if (st->guest_EAX == 0) { st->guest_EAX = 0x1; diff --git a/VEX/priv/guest-x86/toIR.c b/VEX/priv/guest-x86/toIR.c index 906a601d0d..84929efcbf 100644 --- a/VEX/priv/guest-x86/toIR.c +++ b/VEX/priv/guest-x86/toIR.c @@ -590,7 +590,12 @@ static IRExpr* mk_calculate_eflags_all ( void ) args[1] = IRExpr_Get(OFFB_CC_SRC, Ity_I32); args[2] = IRExpr_Get(OFFB_CC_DST, Ity_I32); args[3] = NULL; - return IRExpr_CCall("calculate_eflags_all", Ity_I32, args); + return IRExpr_CCall( + mkIRCallee(0/*regparm*/, "calculate_eflags_all", + (HWord)&calculate_eflags_all), + Ity_I32, + args + ); } /* Build IR to calculate just the carry flag from stored @@ -602,12 +607,17 @@ static IRExpr* mk_calculate_eflags_c ( void ) args[1] = IRExpr_Get(OFFB_CC_SRC, Ity_I32); args[2] = IRExpr_Get(OFFB_CC_DST, Ity_I32); args[3] = NULL; - return IRExpr_CCall("calculate_eflags_c", Ity_I32, args); + return IRExpr_CCall( + mkIRCallee(0/*regparm*/, "calculate_eflags_c", + (HWord)&calculate_eflags_c), + Ity_I32, + args + ); } /* Build IR to calculate some particular condition from stored CC_OP/CC_SRC/CC_DST. Returns an expression :: Ity_Bit. */ -static IRExpr* calculate_condition ( Condcode cond ) +static IRExpr* mk_calculate_condition ( Condcode cond ) { IRExpr** args = LibVEX_Alloc(5 * sizeof(IRExpr*)); args[0] = mkU32(cond); @@ -616,7 +626,13 @@ static IRExpr* calculate_condition ( Condcode cond ) args[3] = IRExpr_Get(OFFB_CC_DST, Ity_I32); args[4] = NULL; return unop(Iop_32to1, - IRExpr_CCall("calculate_condition", Ity_I32, args)); + IRExpr_CCall( + mkIRCallee(0/*regparm*/, "calculate_condition", + (HWord)&calculate_condition), + Ity_I32, + args + ) + ); } @@ -1371,12 +1387,12 @@ static void jcc_01( Condcode cond, Addr32 d32_false, Addr32 d32_true ) Condcode condPos; condPos = positiveIse_Condcode ( cond, &invert ); if (invert) { - stmt( IRStmt_Exit( calculate_condition(condPos), + stmt( IRStmt_Exit( mk_calculate_condition(condPos), IRConst_U32(d32_false) ) ); irbb->next = mkU32(d32_true); irbb->jumpkind = Ijk_Boring; } else { - stmt( IRStmt_Exit( calculate_condition(condPos), + stmt( IRStmt_Exit( mk_calculate_condition(condPos), IRConst_U32(d32_true) ) ); irbb->next = mkU32(d32_false); irbb->jumpkind = Ijk_Boring; @@ -2353,11 +2369,16 @@ UInt dis_Grp2 ( UChar sorb, IRTemp r64 = newTemp(Ity_I64); IRExpr** args = LibVEX_Alloc(5 * sizeof(IRExpr*)); args[0] = widenUto32(mkexpr(dst0)); /* thing to rotate */ - args[1] = widenUto32(shift_expr); /* rotate amount */ + args[1] = widenUto32(shift_expr); /* rotate amount */ args[2] = widenUto32(mk_calculate_eflags_all()); args[3] = mkU32(sz); args[4] = NULL; - assign( r64, IRExpr_CCall("calculate_RCR", Ity_I64, args) ); + assign( r64, IRExpr_CCall( + mkIRCallee(0/*regparm*/, "calculate_RCR", + (HWord)&calculate_RCR), + Ity_I64, + args + )); /* new eflags in hi half r64; new value in lo half r64 */ assign( dst1, narrowTo(ty, unop(Iop_64to32, mkexpr(r64))) ); stmt( IRStmt_Put( OFFB_CC_OP, mkU32(CC_OP_COPY) )); @@ -3152,7 +3173,7 @@ void dis_REP_op ( Condcode cond, if (cond == CondAlways) { jmp_lit(Ijk_Boring,eip); } else { - stmt( IRStmt_Exit( calculate_condition(cond), + stmt( IRStmt_Exit( mk_calculate_condition(cond), IRConst_U32(eip) ) ); jmp_lit(Ijk_Boring,eip_next); } @@ -3772,7 +3793,12 @@ UInt dis_FPU ( Bool* decode_ok, UChar sorb, UInt delta ) args[0] = unop(Iop_8Uto32, get_ST_TAG(0)); args[1] = unop(Iop_ReinterpF64asI64, get_ST_UNCHECKED(0)); args[2] = NULL; - put_C3210(IRExpr_CCall("calculate_FXAM", Ity_I32, args)); + put_C3210(IRExpr_CCall( + mkIRCallee(0/*regparm*/, "calculate_FXAM", + (HWord)&calculate_FXAM), + Ity_I32, + args + )); break; } @@ -3989,7 +4015,7 @@ UInt dis_FPU ( Bool* decode_ok, UChar sorb, UInt delta ) DIP("fcmovz %%st(%d), %%st(0)", r_src); put_ST_UNCHECKED(0, IRExpr_Mux0X( - unop(Iop_1Uto8,calculate_condition(CondZ)), + unop(Iop_1Uto8,mk_calculate_condition(CondZ)), get_ST(0), get_ST(r_src)) ); break; @@ -4054,7 +4080,11 @@ UInt dis_FPU ( Bool* decode_ok, UChar sorb, UInt delta ) IRTemp val = newTemp(Ity_I64); IRExpr** args = mkIRExprVec_1 ( mkexpr(addr) ); - IRDirty* d = unsafeIRDirty_1_N ( val, "loadF80le", args ); + IRDirty* d = unsafeIRDirty_1_N ( + val, + mkIRCallee(0, "loadF80le", (HWord)&loadF80le), + args + ); /* declare that we're reading memory */ d->mFx = Ifx_Read; d->mAddr = mkexpr(addr); @@ -4075,7 +4105,11 @@ UInt dis_FPU ( Bool* decode_ok, UChar sorb, UInt delta ) = mkIRExprVec_2( mkexpr(addr), unop(Iop_ReinterpF64asI64, get_ST(0)) ); - IRDirty* d = unsafeIRDirty_0_N ( "storeF80le", args ); + IRDirty* d = unsafeIRDirty_0_N ( + mkIRCallee(0, "storeF80le", + (HWord)&storeF80le), + args + ); /* declare we're writing memory */ d->mFx = Ifx_Write; d->mAddr = mkexpr(addr); @@ -4105,7 +4139,7 @@ UInt dis_FPU ( Bool* decode_ok, UChar sorb, UInt delta ) DIP("fcmovnz %%st(%d), %%st(0)", r_src); put_ST_UNCHECKED(0, IRExpr_Mux0X( - unop(Iop_1Uto8,calculate_condition(CondNZ)), + unop(Iop_1Uto8,mk_calculate_condition(CondNZ)), get_ST(0), get_ST(r_src)) ); break; @@ -5230,7 +5264,7 @@ UInt dis_cmpxchg_G_E ( UChar sorb, assign( src, getIReg(size, gregOfRM(rm)) ); assign( acc, getIReg(size, R_EAX) ); setFlags_ADD_SUB(Iop_Sub8, dest, acc, ty); - assign( cond8, unop(Iop_1Uto8, calculate_condition(CondZ)) ); + assign( cond8, unop(Iop_1Uto8, mk_calculate_condition(CondZ)) ); assign( dest2, IRExpr_Mux0X(mkexpr(cond8), mkexpr(dest), mkexpr(src)) ); assign( acc2, IRExpr_Mux0X(mkexpr(cond8), mkexpr(dest), mkexpr(acc)) ); putIReg(size, R_EAX, mkexpr(acc2)); @@ -5349,7 +5383,7 @@ UInt dis_cmov_E_G ( UChar sorb, assign( tmpd, getIReg(sz, gregOfRM(rm)) ); putIReg(sz, gregOfRM(rm), - IRExpr_Mux0X( unop(Iop_1Uto8,calculate_condition(cond)), + IRExpr_Mux0X( unop(Iop_1Uto8,mk_calculate_condition(cond)), mkexpr(tmpd), mkexpr(tmps) ) ); @@ -5367,7 +5401,7 @@ UInt dis_cmov_E_G ( UChar sorb, assign( tmpd, getIReg(sz, gregOfRM(rm)) ); putIReg(sz, gregOfRM(rm), - IRExpr_Mux0X( unop(Iop_1Uto8,calculate_condition(cond)), + IRExpr_Mux0X( unop(Iop_1Uto8,mk_calculate_condition(cond)), mkexpr(tmpd), mkexpr(tmps) ) ); @@ -8970,7 +9004,11 @@ static DisResult disInstr ( /*IN*/ Bool resteerOK, declared to mod eax, wr ebx, ecx, edx */ IRExpr** args = mkIRExprVec_0(); - IRDirty* d = unsafeIRDirty_0_N ( "dirtyhelper_CPUID", args ); + IRDirty* d = unsafeIRDirty_0_N ( + mkIRCallee(0, "dirtyhelper_CPUID", + (HWord)&dirtyhelper_CPUID), + args + ); /* declare guest state effects */ d->needsBBP = True; d->nFxState = 4; @@ -9145,7 +9183,7 @@ static DisResult disInstr ( /*IN*/ Bool resteerOK, case 0x9E: /* set-LEb/set-NGb (jump less or equal) */ case 0x9F: /* set-Gb/set-NLEb (jump greater) */ t1 = newTemp(Ity_I8); - assign( t1, unop(Iop_1Uto8,calculate_condition(opc-0x90)) ); + assign( t1, unop(Iop_1Uto8,mk_calculate_condition(opc-0x90)) ); modrm = getIByte(delta); if (epartIsReg(modrm)) { delta++; diff --git a/VEX/priv/host-x86/hdefs.h b/VEX/priv/host-x86/hdefs.h index fd00ef9af0..768c8b9f25 100644 --- a/VEX/priv/host-x86/hdefs.h +++ b/VEX/priv/host-x86/hdefs.h @@ -477,8 +477,7 @@ extern Int emit_X86Instr ( UChar* buf, Int nbuf, X86Instr* ); extern X86Instr* genSpill_X86 ( HReg rreg, Int offset ); extern X86Instr* genReload_X86 ( HReg rreg, Int offset ); extern void getAllocableRegs_X86 ( Int*, HReg** ); -extern HInstrArray* iselBB_X86 ( IRBB*, HWord(*)(Char*), - HWord(*)(Char*) ); +extern HInstrArray* iselBB_X86 ( IRBB* ); #endif /* ndef __LIBVEX_X86H_DEFS_H */ diff --git a/VEX/priv/host-x86/isel.c b/VEX/priv/host-x86/isel.c index e63a557077..f3466a4c79 100644 --- a/VEX/priv/host-x86/isel.c +++ b/VEX/priv/host-x86/isel.c @@ -143,12 +143,6 @@ static IRExpr* bind ( Int binder ) /* This carries around: - - A function for looking up the address of vex front-end supplied - helper functions. - - - A function for looking up the address of tool-supplied helper - functions. - - A mapping from IRTemp to IRType, giving the type of any IRTemp we might encounter. This is computed before insn selection starts, and does not change. @@ -173,9 +167,6 @@ static IRExpr* bind ( Int binder ) typedef struct { - HWord (*find_helper_vex)(Char*); - HWord (*find_helper_tool)(Char*); - IRTypeEnv* type_env; HReg* vregmap; @@ -301,47 +292,16 @@ static Int pushArg ( ISelEnv* env, IRExpr* arg ) } -/* Find the address of a helper function, first by consulting vex's - own front end, and if that doesn't work, by consulting the - tool-supplied lookup function. */ - -static -HWord findHelper ( ISelEnv* env, Char* name ) -{ - HWord helper; - - /* Since the host -- for which we are generating code, and on which - the helpers are compiled -- is a 32-bit machine (x86) -- HWord - must be a 32-bit type. */ - vassert(sizeof(HWord) == 4); - - /* First see if vex's own front end has a binding for this fn. */ - helper = env->find_helper_vex(name); - - /* No? Try the tool-supplied function. */ - if (helper == 0 && env->find_helper_tool) - helper = env->find_helper_tool(name); - - if (helper != 0) - return helper; - - vex_printf("\nvex x86 back end: can't find helper: %s\n", name); - vpanic("findHelper(x86,host)"); -} - - /* Complete the call to a helper function, by calling the helper and clearing the args off the stack. */ static -void callHelperAndClearArgs ( ISelEnv* env, Char* name, Int n_arg_ws ) +void callHelperAndClearArgs ( ISelEnv* env, IRCallee* cee, Int n_arg_ws ) { - HWord helper = findHelper( env, name ); vassert(sizeof(HWord) == 4); - addInstr(env, X86Instr_Alu32R( Xalu_MOV, - X86RMI_Imm(helper), + X86RMI_Imm(cee->addr), hregX86_EAX())); addInstr(env, X86Instr_Call(hregX86_EAX())); if (n_arg_ws > 0) @@ -919,7 +879,7 @@ static HReg iselIntExpr_R_wrk ( ISelEnv* env, IRExpr* e ) n_arg_ws += pushArg(env, e->Iex.CCall.args[i]); /* call the helper, and get the args off the stack afterwards. */ - callHelperAndClearArgs( env, e->Iex.CCall.name, n_arg_ws ); + callHelperAndClearArgs( env, e->Iex.CCall.cee, n_arg_ws ); addInstr(env, mk_MOVsd_RR(hregX86_EAX(), dst)); return dst; @@ -1654,7 +1614,7 @@ static void iselIntExpr64_wrk ( HReg* rHi, HReg* rLo, ISelEnv* env, IRExpr* e ) n_arg_ws += pushArg(env, e->Iex.CCall.args[i]); /* call the helper, and get the args off the stack afterwards. */ - callHelperAndClearArgs( env, e->Iex.CCall.name, n_arg_ws ); + callHelperAndClearArgs( env, e->Iex.CCall.cee, n_arg_ws ); addInstr(env, mk_MOVsd_RR(hregX86_EDX(), tHi)); addInstr(env, mk_MOVsd_RR(hregX86_EAX(), tLo)); @@ -2173,7 +2133,7 @@ static void iselStmt ( ISelEnv* env, IRStmt* stmt ) } /* call the helper, and get the args off the stack afterwards. */ - callHelperAndClearArgs( env, d->name, n_arg_ws ); + callHelperAndClearArgs( env, d->cee, n_arg_ws ); /* Now figure out what to do with the returned value, if any. */ if (d->tmp == INVALID_IRTEMP) @@ -2237,9 +2197,7 @@ static void iselNext ( ISelEnv* env, IRExpr* next, IRJumpKind jk ) /* Translate an entire BB to x86 code. */ -HInstrArray* iselBB_X86 ( IRBB* bb, - HWord(*find_helper_vex)(Char*), - HWord(*find_helper_tool)(Char*) ) +HInstrArray* iselBB_X86 ( IRBB* bb ) { Int i, j; HReg hreg, hregHI; @@ -2248,10 +2206,6 @@ HInstrArray* iselBB_X86 ( IRBB* bb, ISelEnv* env = LibVEX_Alloc(sizeof(ISelEnv)); env->vreg_ctr = 0; - /* Register helper-function-finders. */ - env->find_helper_vex = find_helper_vex; - env->find_helper_tool = find_helper_tool; - /* Set up output code array. */ env->code = newHInstrArray(); diff --git a/VEX/priv/ir/irdefs.c b/VEX/priv/ir/irdefs.c index 935d368156..19b30ec686 100644 --- a/VEX/priv/ir/irdefs.c +++ b/VEX/priv/ir/irdefs.c @@ -48,6 +48,14 @@ void ppIRConst ( IRConst* con ) } } +void ppIRCallee ( IRCallee* ce ) +{ + vex_printf("%s", ce->name); + if (ce->regparm > 0) + vex_printf("[%d]", ce->regparm); + vex_printf("{%p}", (void*)ce->addr); +} + void ppIRArray ( IRArray* arr ) { vex_printf("(%d:%dx", arr->base, arr->nElems); @@ -237,7 +245,8 @@ void ppIRExpr ( IRExpr* e ) ppIRConst(e->Iex.Const.con); break; case Iex_CCall: - vex_printf("%s(", e->Iex.CCall.name); + ppIRCallee(e->Iex.CCall.cee); + vex_printf("("); for (i = 0; e->Iex.CCall.args[i] != NULL; i++) { ppIRExpr(e->Iex.CCall.args[i]); if (e->Iex.CCall.args[i+1] != NULL) @@ -294,7 +303,8 @@ void ppIRDirty ( IRDirty* d ) ppIRTemp(d->tmp); vex_printf(" = "); } - vex_printf("%s(", d->name); + ppIRCallee(d->cee); + vex_printf("("); for (i = 0; d->args[i] != NULL; i++) { ppIRExpr(d->args[i]); if (d->args[i+1] != NULL) { @@ -453,7 +463,22 @@ IRConst* IRConst_F64i ( ULong f64i ) } -/* Constructors -- IRExpr */ +/* Constructors -- IRCallee */ + +IRCallee* mkIRCallee ( Int regparm, Char* name, HWord addr ) +{ + IRCallee* ce = LibVEX_Alloc(sizeof(IRCallee)); + ce->regparm = regparm; + ce->name = name; + ce->addr = addr; + vassert(regparm >= 0); + vassert(name != NULL); + vassert(addr != 0); + return ce; +} + + +/* Constructors -- IRArray */ IRArray* mkIRArray ( Int base, IRType elemTy, Int nElems ) { @@ -525,10 +550,10 @@ IRExpr* IRExpr_Const ( IRConst* con ) { e->Iex.Const.con = con; return e; } -IRExpr* IRExpr_CCall ( Char* name, IRType retty, IRExpr** args ) { +IRExpr* IRExpr_CCall ( IRCallee* cee, IRType retty, IRExpr** args ) { IRExpr* e = LibVEX_Alloc(sizeof(IRExpr)); e->tag = Iex_CCall; - e->Iex.CCall.name = name; + e->Iex.CCall.cee = cee; e->Iex.CCall.retty = retty; e->Iex.CCall.args = args; return e; @@ -570,7 +595,7 @@ IRExpr** mkIRExprVec_2 ( IRExpr* arg1, IRExpr* arg2 ) { IRDirty* emptyIRDirty ( void ) { IRDirty* d = LibVEX_Alloc(sizeof(IRDirty)); - d->name = NULL; + d->cee = NULL; d->args = NULL; d->tmp = INVALID_IRTEMP; d->mFx = Ifx_None; @@ -581,15 +606,15 @@ IRDirty* emptyIRDirty ( void ) { return d; } -IRDirty* unsafeIRDirty_0_N ( Char* name, IRExpr** args ) { +IRDirty* unsafeIRDirty_0_N ( IRCallee* cee, IRExpr** args ) { IRDirty* d = emptyIRDirty(); - d->name = name; + d->cee = cee; d->args = args; return d; } -IRDirty* unsafeIRDirty_1_N ( IRTemp dst, Char* name, IRExpr** args ) { +IRDirty* unsafeIRDirty_1_N ( IRTemp dst, IRCallee* cee, IRExpr** args ) { IRDirty* d = emptyIRDirty(); - d->name = name; + d->cee = cee; d->args = args; d->tmp = dst; return d; @@ -722,6 +747,11 @@ IRConst* dopyIRConst ( IRConst* c ) } } +IRCallee* dopyIRCallee ( IRCallee* ce ) +{ + return mkIRCallee(ce->regparm, ce->name, ce->addr); +} + IRArray* dopyIRArray ( IRArray* d ) { return mkIRArray(d->base, d->elemTy, d->nElems); @@ -751,7 +781,7 @@ IRExpr* dopyIRExpr ( IRExpr* e ) case Iex_Const: return IRExpr_Const(dopyIRConst(e->Iex.Const.con)); case Iex_CCall: - return IRExpr_CCall(e->Iex.CCall.name, + return IRExpr_CCall(dopyIRCallee(e->Iex.CCall.cee), e->Iex.CCall.retty, dopyIRExprVec(e->Iex.CCall.args)); @@ -768,7 +798,7 @@ IRDirty* dopyIRDirty ( IRDirty* d ) { Int i; IRDirty* d2 = emptyIRDirty(); - d2->name = d->name; + d2->cee = dopyIRCallee(d->cee); d2->args = dopyIRExprVec(d->args); d2->tmp = d->tmp; d2->mFx = d->mFx; @@ -1144,6 +1174,17 @@ static Bool saneIRArray ( IRArray* arr ) return True; } +static Bool saneIRCallee ( IRCallee* cee ) +{ + if (cee->name == NULL) + return False; + if (cee->addr == 0) + return False; + if (cee->regparm < 0 || cee->regparm > 3) + return False; + return True; +} + /* Traverse a Stmt/Expr, inspecting IRTemp uses. Report any out of range ones. Report any which are read and for which the current @@ -1367,7 +1408,8 @@ void tcStmt ( IRBB* bb, IRStmt* stmt, IRType gWordTy ) case Ist_Dirty: /* Mostly check for various kinds of ill-formed dirty calls. */ d = stmt->Ist.Dirty.details; - if (d->name == NULL) goto bad_dirty; + if (d->cee == NULL) goto bad_dirty; + if (!saneIRCallee(d->cee)) goto bad_dirty; if (d->mFx == Ifx_None) { if (d->mAddr != NULL || d->mSize != 0) goto bad_dirty; diff --git a/VEX/priv/ir/iropt.c b/VEX/priv/ir/iropt.c index b31814c3c4..48abdfa3d3 100644 --- a/VEX/priv/ir/iropt.c +++ b/VEX/priv/ir/iropt.c @@ -220,7 +220,7 @@ static IRExpr* flatten_Expr ( IRBB* bb, IRExpr* ex ) newargs[i] = flatten_Expr(bb, newargs[i]); t1 = newIRTemp(bb->tyenv, ty); addStmtToIRBB(bb, IRStmt_Tmp(t1, - IRExpr_CCall(ex->Iex.CCall.name, + IRExpr_CCall(ex->Iex.CCall.cee, ex->Iex.CCall.retty, newargs))); return IRExpr_Tmp(t1); @@ -656,7 +656,7 @@ static IRExpr* subst_Expr ( IRExpr** env, IRExpr* ex ) args2[i] = subst_Expr(env, args2[i]); } return IRExpr_CCall( - ex->Iex.CCall.name, + ex->Iex.CCall.cee, ex->Iex.CCall.retty, args2 ); @@ -1362,7 +1362,7 @@ void spec_helpers_BB ( IRBB* bb, || st->Ist.Tmp.data->tag != Iex_CCall) continue; - ex = (*specHelper)( st->Ist.Tmp.data->Iex.CCall.name, + ex = (*specHelper)( st->Ist.Tmp.data->Iex.CCall.cee->name, st->Ist.Tmp.data->Iex.CCall.args ); if (!ex) /* the front end can't think of a suitable replacement */ @@ -1548,7 +1548,7 @@ static IRExpr* tbSubst_Expr ( TmpInfo** env, IRExpr* e ) args2 = sopyIRExprVec(e->Iex.CCall.args); for (i = 0; args2[i]; i++) args2[i] = tbSubst_Expr(env,args2[i]); - return IRExpr_CCall(e->Iex.CCall.name, + return IRExpr_CCall(e->Iex.CCall.cee, e->Iex.CCall.retty, args2 ); diff --git a/VEX/priv/main/vex_main.c b/VEX/priv/main/vex_main.c index 1baf976c37..d61c561d07 100644 --- a/VEX/priv/main/vex_main.c +++ b/VEX/priv/main/vex_main.c @@ -128,7 +128,6 @@ TranslateResult LibVEX_Translate ( /* 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 ), /* IN: debug: trace vex activity at various points */ @@ -147,11 +146,10 @@ TranslateResult LibVEX_Translate ( HInstr* (*genReload) ( HReg, Int ); void (*ppInstr) ( HInstr* ); void (*ppReg) ( HReg ); - HInstrArray* (*iselBB) ( IRBB*, HWord(*)(Char*), HWord(*)(Char*) ); + HInstrArray* (*iselBB) ( IRBB* ); IRBB* (*bbToIR) ( UChar*, Addr64, Int*, Bool(*)(Addr64), Bool ); Int (*emit) ( UChar*, Int, HInstr* ); - HWord (*findHelper) ( Char* ); IRExpr* (*specHelper) ( Char*, IRExpr** ); Bool (*preciseMemExnsFn) ( Int, Int ); @@ -177,7 +175,6 @@ TranslateResult LibVEX_Translate ( iselBB = NULL; bbToIR = NULL; emit = NULL; - findHelper = NULL; specHelper = NULL; preciseMemExnsFn = NULL; guest_word_size = Ity_INVALID; @@ -212,7 +209,6 @@ TranslateResult LibVEX_Translate ( case InsnSetX86: preciseMemExnsFn = guest_x86_state_requires_precise_mem_exns; bbToIR = bbToIR_X86Instr; - findHelper = x86guest_findhelper; specHelper = x86guest_spechelper; guest_sizeB = sizeof(VexGuestX86State); guest_word_size = Ity_I32; @@ -299,7 +295,7 @@ TranslateResult LibVEX_Translate ( " Instruction selection " "------------------------\n"); - vcode = iselBB ( irbb, findHelper, tool_findhelper ); + vcode = iselBB ( irbb ); if (vex_traceflags & VEX_TRACE_VCODE) vex_printf("\n"); diff --git a/VEX/pub/libvex.h b/VEX/pub/libvex.h index 58412ee735..e69b8cc349 100644 --- a/VEX/pub/libvex.h +++ b/VEX/pub/libvex.h @@ -129,7 +129,6 @@ TranslateResult LibVEX_Translate ( /* 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 ), /* IN: debug: trace vex activity at various points */ diff --git a/VEX/pub/libvex_ir.h b/VEX/pub/libvex_ir.h index 3bc311c03b..a6130d62c4 100644 --- a/VEX/pub/libvex_ir.h +++ b/VEX/pub/libvex_ir.h @@ -70,6 +70,30 @@ extern void ppIRConst ( IRConst* ); extern Bool eqIRConst ( IRConst*, IRConst* ); +/* ------------------ Call targets ------------------ */ + +/* Describes a helper function to call. The name part is purely for + pretty printing and not actually used. regparm=n tells the back + end that the callee has been declared + "__attribute__((regparm(n)))". On some targets (x86) the back end + will need to construct a non-standard sequence to call a function + declared like this. */ + +typedef + struct { + Int regparm; + Char* name; + HWord addr; + } + IRCallee; + +extern IRCallee* mkIRCallee ( Int regparm, Char* name, HWord addr ); + +extern IRCallee* dopyIRCallee ( IRCallee* ); + +extern void ppIRCallee ( IRCallee* ); + + /* ------------------ Guest state arrays ------------------ */ typedef @@ -378,8 +402,8 @@ typedef IRConst* con; } Const; struct { - Char* name; - IRType retty; + IRCallee* cee; + IRType retty; struct _IRExpr** args; } CCall; struct { @@ -399,7 +423,7 @@ extern IRExpr* IRExpr_Binop ( IROp op, IRExpr* arg1, IRExpr* arg2 ); extern IRExpr* IRExpr_Unop ( IROp op, IRExpr* arg ); extern IRExpr* IRExpr_LDle ( IRType ty, IRExpr* addr ); extern IRExpr* IRExpr_Const ( IRConst* con ); -extern IRExpr* IRExpr_CCall ( Char* name, IRType retty, IRExpr** args ); +extern IRExpr* IRExpr_CCall ( IRCallee* cee, IRType retty, IRExpr** args ); extern IRExpr* IRExpr_Mux0X ( IRExpr* cond, IRExpr* expr0, IRExpr* exprX ); extern IRExpr* dopyIRExpr ( IRExpr* ); @@ -479,14 +503,14 @@ extern void ppIREffect ( IREffect ); typedef struct { /* What to call, and details of args/results */ - Char* name; /* name of the function to call */ - IRExpr** args; /* arg list, ends in NULL */ - IRTemp tmp; /* to assign result to, or INVALID_IRTEMP if none */ + IRCallee* cee; /* where to call */ + IRExpr** args; /* arg list, ends in NULL */ + IRTemp tmp; /* to assign result to, or INVALID_IRTEMP if none */ /* Mem effects; we allow only one R/W/M region to be stated */ - IREffect mFx; /* indicates memory effects, if any */ - IRExpr* mAddr; /* of access, or NULL if mFx==Ifx_None */ - Int mSize; /* of access, or zero if mFx==Ifx_None */ + IREffect mFx; /* indicates memory effects, if any */ + IRExpr* mAddr; /* of access, or NULL if mFx==Ifx_None */ + Int mSize; /* of access, or zero if mFx==Ifx_None */ /* Guest state effects; up to N allowed */ Bool needsBBP; /* True => also pass guest state ptr to callee */ @@ -509,11 +533,11 @@ extern IRDirty* dopyIRDirty ( IRDirty* ); any value. The call is marked as accessing neither guest state nor memory (hence the "unsafe" designation) -- you can mess with this later if need be.*/ -extern IRDirty* unsafeIRDirty_0_N ( Char* name, IRExpr** args ); +extern IRDirty* unsafeIRDirty_0_N ( IRCallee* cee, IRExpr** args ); /* Similarly, make a zero-annotation dirty call which returns a value, and assign that to the given temp. */ -extern IRDirty* unsafeIRDirty_1_N ( IRTemp dst, Char* name, IRExpr** args ); +extern IRDirty* unsafeIRDirty_1_N ( IRTemp dst, IRCallee* cee, IRExpr** args ); /* ------------------ Statements ------------------ */