|
From: <sv...@va...> - 2013-01-16 09:29:47
|
sewardj 2013-01-16 09:29:37 +0000 (Wed, 16 Jan 2013)
New Revision: 2638
Log:
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.
Modified files:
branches/COMEM/priv/host_x86_defs.c
branches/COMEM/priv/host_x86_defs.h
branches/COMEM/priv/host_x86_isel.c
Modified: branches/COMEM/priv/host_x86_defs.h (+2 -1)
===================================================================
--- branches/COMEM/priv/host_x86_defs.h 2013-01-16 09:22:27 +00:00 (rev 2637)
+++ branches/COMEM/priv/host_x86_defs.h 2013-01-16 09:29:37 +00:00 (rev 2638)
@@ -450,6 +450,7 @@
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_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,
Modified: branches/COMEM/priv/host_x86_defs.c (+16 -3)
===================================================================
--- branches/COMEM/priv/host_x86_defs.c 2013-01-16 09:22:27 +00:00 (rev 2637)
+++ branches/COMEM/priv/host_x86_defs.c 2013-01-16 09:29:37 +00:00 (rev 2638)
@@ -638,13 +638,16 @@
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 @@
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 @@
}
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) {
Modified: branches/COMEM/priv/host_x86_isel.c (+50 -17)
===================================================================
--- branches/COMEM/priv/host_x86_isel.c 2013-01-16 09:22:27 +00:00 (rev 2637)
+++ branches/COMEM/priv/host_x86_isel.c 2013-01-16 09:29:37 +00:00 (rev 2638)
@@ -366,7 +366,8 @@
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 @@
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 @@
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 @@
}
/* 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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
/* --------- Call to DIRTY helper --------- */
case Ist_Dirty: {
- IRType retty;
IRDirty* d = stmt->Ist.Dirty.details;
Bool passBBP = False;
@@ -3969,15 +3979,38 @@
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
|