From: Julian Seward Date: Wed, 16 Jan 2013 09:29:37 +0000 (+0000) Subject: x86 equivalent to r2636: fix up the x86 back end to be in sync with X-Git-Tag: svn/VALGRIND_3_9_0^2~152^2~3 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=031cf42e26d035095f8c919f4a6200db891efe82;p=thirdparty%2Fvalgrind.git x86 equivalent to r2636: fix up the x86 back end to be in sync with infrastructural changes w.r.t. conditional dirty helpers that return values. Does not actually handle such cases since the x86 front end does not generate them. git-svn-id: svn://svn.valgrind.org/vex/branches/COMEM@2638 --- diff --git a/VEX/priv/host_x86_defs.c b/VEX/priv/host_x86_defs.c index 591ac75d1b..ecfaa14744 100644 --- a/VEX/priv/host_x86_defs.c +++ b/VEX/priv/host_x86_defs.c @@ -638,13 +638,16 @@ X86Instr* X86Instr_Push( X86RMI* src ) { i->Xin.Push.src = src; return i; } -X86Instr* X86Instr_Call ( X86CondCode cond, Addr32 target, Int regparms ) { +X86Instr* X86Instr_Call ( X86CondCode cond, Addr32 target, Int regparms, + RetLoc rloc ) { X86Instr* i = LibVEX_Alloc(sizeof(X86Instr)); i->tag = Xin_Call; i->Xin.Call.cond = cond; i->Xin.Call.target = target; i->Xin.Call.regparms = regparms; + i->Xin.Call.rloc = rloc; vassert(regparms >= 0 && regparms <= 3); + vassert(rloc != RetLocINVALID); return i; } X86Instr* X86Instr_XDirect ( Addr32 dstGA, X86AMode* amEIP, @@ -980,11 +983,12 @@ void ppX86Instr ( X86Instr* i, Bool mode64 ) { ppX86RMI(i->Xin.Push.src); return; case Xin_Call: - vex_printf("call%s[%d] ", + vex_printf("call%s[%d,", i->Xin.Call.cond==Xcc_ALWAYS ? "" : showX86CondCode(i->Xin.Call.cond), i->Xin.Call.regparms); - vex_printf("0x%x", i->Xin.Call.target); + ppRetLoc(i->Xin.Call.rloc); + vex_printf("] 0x%x", i->Xin.Call.target); break; case Xin_XDirect: vex_printf("(xDirect) "); @@ -2375,6 +2379,15 @@ Int emit_X86Instr ( /*MB_MOD*/Bool* is_profInc, } case Xin_Call: + if (i->Xin.Call.cond != Xcc_ALWAYS && i->Xin.Call.rloc != RetLocNone) { + /* The call might not happen (it isn't unconditional) and it + returns a result. In this case we will need to generate a + control flow diamond to put 0x555..555 in the return + register(s) in the case where the call doesn't happen. If + this ever becomes necessary, maybe copy code from the ARM + equivalent. Until that day, just give up. */ + goto bad; + } /* See detailed comment for Xin_Call in getRegUsage_X86Instr above for explanation of this. */ switch (i->Xin.Call.regparms) { diff --git a/VEX/priv/host_x86_defs.h b/VEX/priv/host_x86_defs.h index 3d809f4ea9..f810ab4f61 100644 --- a/VEX/priv/host_x86_defs.h +++ b/VEX/priv/host_x86_defs.h @@ -450,6 +450,7 @@ typedef X86CondCode cond; Addr32 target; Int regparms; /* 0 .. 3 */ + RetLoc rloc; /* where the return value will be */ } Call; /* Update the guest EIP value, then exit requesting to chain to it. May be conditional. Urr, use of Addr32 implicitly @@ -664,7 +665,7 @@ extern X86Instr* X86Instr_MulL ( Bool syned, X86RM* ); extern X86Instr* X86Instr_Div ( Bool syned, X86RM* ); extern X86Instr* X86Instr_Sh3232 ( X86ShiftOp, UInt amt, HReg src, HReg dst ); extern X86Instr* X86Instr_Push ( X86RMI* ); -extern X86Instr* X86Instr_Call ( X86CondCode, Addr32, Int ); +extern X86Instr* X86Instr_Call ( X86CondCode, Addr32, Int, RetLoc ); extern X86Instr* X86Instr_XDirect ( Addr32 dstGA, X86AMode* amEIP, X86CondCode cond, Bool toFastEP ); extern X86Instr* X86Instr_XIndir ( HReg dstGA, X86AMode* amEIP, diff --git a/VEX/priv/host_x86_isel.c b/VEX/priv/host_x86_isel.c index 5513d7157a..7885c21109 100644 --- a/VEX/priv/host_x86_isel.c +++ b/VEX/priv/host_x86_isel.c @@ -366,7 +366,8 @@ static Int pushArg ( ISelEnv* env, IRExpr* arg ) static void callHelperAndClearArgs ( ISelEnv* env, X86CondCode cc, - IRCallee* cee, Int n_arg_ws ) + IRCallee* cee, Int n_arg_ws, + RetLoc rloc ) { /* Complication. Need to decide which reg to use as the fn address pointer, in a way that doesn't trash regparm-passed @@ -374,7 +375,7 @@ void callHelperAndClearArgs ( ISelEnv* env, X86CondCode cc, vassert(sizeof(void*) == 4); addInstr(env, X86Instr_Call( cc, toUInt(Ptr_to_ULong(cee->addr)), - cee->regparms)); + cee->regparms, rloc)); if (n_arg_ws > 0) add_to_esp(env, 4*n_arg_ws); } @@ -404,7 +405,8 @@ Bool mightRequireFixedRegs ( IRExpr* e ) static void doHelperCall ( ISelEnv* env, Bool passBBP, - IRExpr* guard, IRCallee* cee, IRExpr** args ) + IRExpr* guard, IRCallee* cee, IRExpr** args, + RetLoc rloc ) { X86CondCode cc; HReg argregs[3]; @@ -583,7 +585,7 @@ void doHelperCall ( ISelEnv* env, } /* call the helper, and get the args off the stack afterwards. */ - callHelperAndClearArgs( env, cc, cee, n_arg_ws ); + callHelperAndClearArgs( env, cc, cee, n_arg_ws, rloc ); } @@ -1304,7 +1306,8 @@ static HReg iselIntExpr_R_wrk ( ISelEnv* env, IRExpr* e ) iselInt64Expr(&xHi, &xLo, env, e->Iex.Unop.arg); addInstr(env, X86Instr_Push(X86RMI_Reg(xHi))); addInstr(env, X86Instr_Push(X86RMI_Reg(xLo))); - addInstr(env, X86Instr_Call( Xcc_ALWAYS, (UInt)fn, 0 )); + addInstr(env, X86Instr_Call( Xcc_ALWAYS, (UInt)fn, + 0, RetLocInt )); add_to_esp(env, 2*4); addInstr(env, mk_iMOVsd_RR(hregX86_EAX(), dst)); return dst; @@ -1361,13 +1364,15 @@ static HReg iselIntExpr_R_wrk ( ISelEnv* env, IRExpr* e ) HReg dst = newVRegI(env); vassert(ty == e->Iex.CCall.retty); - /* be very restrictive for now. Only 32/64-bit ints allowed - for args, and 32 bits for return type. */ + /* be very restrictive for now. Only 32/64-bit ints allowed for + args, and 32 bits for return type. Don't forget to change + the RetLoc if more return types are allowed in future. */ if (e->Iex.CCall.retty != Ity_I32) goto irreducible; /* Marshal args, do the call, clear stack. */ - doHelperCall( env, False, NULL, e->Iex.CCall.cee, e->Iex.CCall.args ); + doHelperCall( env, False, NULL, e->Iex.CCall.cee, + e->Iex.CCall.args, RetLocInt ); addInstr(env, mk_iMOVsd_RR(hregX86_EAX(), dst)); return dst; @@ -1887,7 +1892,8 @@ static X86CondCode iselCondCode_wrk ( ISelEnv* env, IRExpr* e ) vassert(cal->Iex.CCall.retty == Ity_I32); /* else ill-typed IR */ vassert(con->Iex.Const.con->tag == Ico_U32); /* Marshal args, do the call. */ - doHelperCall( env, False, NULL, cal->Iex.CCall.cee, cal->Iex.CCall.args ); + doHelperCall( env, False, NULL, cal->Iex.CCall.cee, + cal->Iex.CCall.args, RetLocInt ); addInstr(env, X86Instr_Alu32R(Xalu_CMP, X86RMI_Imm(con->Iex.Const.con->Ico.U32), hregX86_EAX())); @@ -2470,7 +2476,8 @@ static void iselInt64Expr_wrk ( HReg* rHi, HReg* rLo, ISelEnv* env, IRExpr* e ) iselInt64Expr(&xHi, &xLo, env, e->Iex.Binop.arg1); addInstr(env, X86Instr_Push(X86RMI_Reg(xHi))); addInstr(env, X86Instr_Push(X86RMI_Reg(xLo))); - addInstr(env, X86Instr_Call( Xcc_ALWAYS, (UInt)fn, 0 )); + addInstr(env, X86Instr_Call( Xcc_ALWAYS, (UInt)fn, + 0, RetLoc2Int )); add_to_esp(env, 4*4); addInstr(env, mk_iMOVsd_RR(hregX86_EDX(), tHi)); addInstr(env, mk_iMOVsd_RR(hregX86_EAX(), tLo)); @@ -2509,7 +2516,8 @@ static void iselInt64Expr_wrk ( HReg* rHi, HReg* rLo, ISelEnv* env, IRExpr* e ) iselInt64Expr(&xHi, &xLo, env, e->Iex.Binop.arg1); addInstr(env, X86Instr_Push(X86RMI_Reg(xHi))); addInstr(env, X86Instr_Push(X86RMI_Reg(xLo))); - addInstr(env, X86Instr_Call( Xcc_ALWAYS, (UInt)fn, 0 )); + addInstr(env, X86Instr_Call( Xcc_ALWAYS, (UInt)fn, + 0, RetLoc2Int )); add_to_esp(env, 3*4); addInstr(env, mk_iMOVsd_RR(hregX86_EDX(), tHi)); addInstr(env, mk_iMOVsd_RR(hregX86_EAX(), tLo)); @@ -2747,7 +2755,8 @@ static void iselInt64Expr_wrk ( HReg* rHi, HReg* rLo, ISelEnv* env, IRExpr* e ) iselInt64Expr(&xHi, &xLo, env, e->Iex.Unop.arg); addInstr(env, X86Instr_Push(X86RMI_Reg(xHi))); addInstr(env, X86Instr_Push(X86RMI_Reg(xLo))); - addInstr(env, X86Instr_Call( Xcc_ALWAYS, (UInt)fn, 0 )); + addInstr(env, X86Instr_Call( Xcc_ALWAYS, (UInt)fn, + 0, RetLoc2Int )); add_to_esp(env, 2*4); addInstr(env, mk_iMOVsd_RR(hregX86_EDX(), tHi)); addInstr(env, mk_iMOVsd_RR(hregX86_EAX(), tLo)); @@ -2768,7 +2777,8 @@ static void iselInt64Expr_wrk ( HReg* rHi, HReg* rLo, ISelEnv* env, IRExpr* e ) HReg tHi = newVRegI(env); /* Marshal args, do the call, clear stack. */ - doHelperCall( env, False, NULL, e->Iex.CCall.cee, e->Iex.CCall.args ); + doHelperCall( env, False, NULL, e->Iex.CCall.cee, + e->Iex.CCall.args, RetLoc2Int ); addInstr(env, mk_iMOVsd_RR(hregX86_EDX(), tHi)); addInstr(env, mk_iMOVsd_RR(hregX86_EAX(), tLo)); @@ -3692,7 +3702,8 @@ static HReg iselVecExpr_wrk ( ISelEnv* env, IRExpr* e ) addInstr(env, X86Instr_SseLdSt(False/*!isLoad*/, argR, X86AMode_IR(0, hregX86_ECX()))); /* call the helper */ - addInstr(env, X86Instr_Call( Xcc_ALWAYS, (Addr32)fn, 3 )); + addInstr(env, X86Instr_Call( Xcc_ALWAYS, (Addr32)fn, + 3, RetLocNone )); /* fetch the result from memory, using %r_argp, which the register allocator will keep alive across the call. */ addInstr(env, X86Instr_SseLdSt(True/*isLoad*/, dst, @@ -3960,7 +3971,6 @@ static void iselStmt ( ISelEnv* env, IRStmt* stmt ) /* --------- Call to DIRTY helper --------- */ case Ist_Dirty: { - IRType retty; IRDirty* d = stmt->Ist.Dirty.details; Bool passBBP = False; @@ -3969,15 +3979,38 @@ static void iselStmt ( ISelEnv* env, IRStmt* stmt ) passBBP = toBool(d->nFxState > 0 && d->needsBBP); + /* Figure out the return type, if any. */ + IRType retty = Ity_INVALID; + if (d->tmp != IRTemp_INVALID) + retty = typeOfIRTemp(env->type_env, d->tmp); + + /* Marshal args, do the call, clear stack, set the return value + to 0x555..555 if this is a conditional call that returns a + value and the call is skipped. We need to set the ret-loc + correctly in order to implement the IRDirty semantics that + the return value is 0x555..555 if the call doesn't happen. */ + RetLoc rloc = RetLocINVALID; + switch (retty) { + case Ity_INVALID: /* function doesn't return anything */ + rloc = RetLocNone; break; + case Ity_I64: + rloc = RetLoc2Int; break; + case Ity_I32: case Ity_I16: case Ity_I8: + rloc = RetLocInt; break; + default: + break; + } + if (rloc == RetLocINVALID) + break; /* will go to stmt_fail: */ + /* Marshal args, do the call, clear stack. */ - doHelperCall( env, passBBP, d->guard, d->cee, d->args ); + doHelperCall( env, passBBP, d->guard, d->cee, d->args, rloc ); /* Now figure out what to do with the returned value, if any. */ if (d->tmp == IRTemp_INVALID) /* No return value. Nothing to do. */ return; - retty = typeOfIRTemp(env->type_env, d->tmp); if (retty == Ity_I64) { HReg dstHi, dstLo; /* The returned value is in %edx:%eax. Park it in the