]> git.ipfire.org Git - thirdparty/valgrind.git/commitdiff
x86 equivalent to r2636: fix up the x86 back end to be in sync with
authorJulian Seward <jseward@acm.org>
Wed, 16 Jan 2013 09:29:37 +0000 (09:29 +0000)
committerJulian Seward <jseward@acm.org>
Wed, 16 Jan 2013 09:29:37 +0000 (09:29 +0000)
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

VEX/priv/host_x86_defs.c
VEX/priv/host_x86_defs.h
VEX/priv/host_x86_isel.c

index 591ac75d1bb502775cc890c3ce956433f6ced5b1..ecfaa14744e156e8cee8ebd3f95d0203b84f00bd 100644 (file)
@@ -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) {
index 3d809f4ea926d740a0780fc237682d30b93b3f4f..f810ab4f615fabb2101560ed55e174d0bd2c01d2 100644 (file)
@@ -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,
index 5513d7157a184f117f451aa274d138720e54458a..7885c211098b2612d271cdeaa26b8028c1cb7c28 100644 (file)
@@ -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