]> git.ipfire.org Git - thirdparty/valgrind.git/commitdiff
mips32 equivalent to r2636: fix up the mips32 back end to be in sync
authorJulian Seward <jseward@acm.org>
Wed, 16 Jan 2013 22:11:13 +0000 (22:11 +0000)
committerJulian Seward <jseward@acm.org>
Wed, 16 Jan 2013 22:11:13 +0000 (22:11 +0000)
with infrastructural changes w.r.t. conditional dirty helpers that
return values.  Does not actually handle such cases since the mips32
front end does not generate them.

git-svn-id: svn://svn.valgrind.org/vex/branches/COMEM@2641

VEX/priv/host_mips_defs.c
VEX/priv/host_mips_defs.h
VEX/priv/host_mips_isel.c

index 1f5151d22e0bbb55bca2475a4aeade54ef4c82b4..9f0a602be34ff9d780efce18b3e701cfc8fc0f6e 100644 (file)
@@ -1217,7 +1217,7 @@ MIPSInstr *MIPSInstr_Div(Bool syned, Bool sz32, HReg srcL, HReg srcR)
 }
 
 MIPSInstr *MIPSInstr_Call(MIPSCondCode cond, Addr32 target, UInt argiregs,
-                          HReg src)
+                          HReg src, RetLoc rloc)
 {
    UInt mask;
    MIPSInstr *i = LibVEX_Alloc(sizeof(MIPSInstr));
@@ -1226,13 +1226,16 @@ MIPSInstr *MIPSInstr_Call(MIPSCondCode cond, Addr32 target, UInt argiregs,
    i->Min.Call.target = target;
    i->Min.Call.argiregs = argiregs;
    i->Min.Call.src = src;
+   i->Min.Call.rloc = rloc;
    /* Only r4 .. r7 inclusive may be used as arg regs. Hence: */
    mask = (1 << 4) | (1 << 5) | (1 << 6) | (1 << 7);
    vassert(0 == (argiregs & ~mask));
+   vassert(rloc != RetLocINVALID);
    return i;
 }
 
-MIPSInstr *MIPSInstr_CallAlways(MIPSCondCode cond, Addr32 target, UInt argiregs)
+MIPSInstr *MIPSInstr_CallAlways(MIPSCondCode cond, Addr32 target, UInt argiregs,
+                                RetLoc rloc)
 {
    UInt mask;
    MIPSInstr *i = LibVEX_Alloc(sizeof(MIPSInstr));
@@ -1240,9 +1243,11 @@ MIPSInstr *MIPSInstr_CallAlways(MIPSCondCode cond, Addr32 target, UInt argiregs)
    i->Min.Call.cond = cond;
    i->Min.Call.target = target;
    i->Min.Call.argiregs = argiregs;
+   i->Min.Call.rloc = rloc;
    /* Only r4 .. r7 inclusive may be used as arg regs. Hence: */
    mask = (1 << 4) | (1 << 5) | (1 << 6) | (1 << 7);
    vassert(0 == (argiregs & ~mask));
+   vassert(rloc != RetLocINVALID);
    return i;
 }
 
@@ -1611,6 +1616,8 @@ void ppMIPSInstr(MIPSInstr * i, Bool mode64)
                   vex_printf(",");
             }
          }
+         vex_printf(",");
+         ppRetLoc(i->Min.Call.rloc);
          vex_printf("] }");
          break;
       }
@@ -3118,6 +3125,16 @@ Int emit_MIPSInstr ( /*MB_MOD*/Bool* is_profInc,
       }
    
       case Min_Call: {
+         if (i->Min.Call.cond != MIPScc_AL && i->Min.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;
+         }
          MIPSCondCode cond = i->Min.Call.cond;
          UInt r_dst = 25;  /* using %r25 as address temporary - 
                      see getRegUsage_MIPSInstr */
index 6de01d21c179a80ed72110c485730aa33d9ca0f6..fbcf3fb337df4d4bd3c7c3383f37eef9a94bb28c 100644 (file)
@@ -493,6 +493,7 @@ typedef struct {
          Addr32 target;
          UInt argiregs;
          HReg src;
+         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
@@ -654,8 +655,8 @@ extern MIPSInstr *MIPSInstr_LoadL(UChar sz, HReg dst, MIPSAMode * src,
 extern MIPSInstr *MIPSInstr_StoreC(UChar sz, MIPSAMode * dst, HReg src,
                                    Bool mode64);
 
-extern MIPSInstr *MIPSInstr_Call(MIPSCondCode, Addr32, UInt, HReg);
-extern MIPSInstr *MIPSInstr_CallAlways(MIPSCondCode, Addr32, UInt);
+extern MIPSInstr *MIPSInstr_Call(MIPSCondCode, Addr32, UInt, HReg, RetLoc);
+extern MIPSInstr *MIPSInstr_CallAlways(MIPSCondCode, Addr32, UInt, RetLoc);
 
 extern MIPSInstr *MIPSInstr_XDirect(Addr32 dstGA, MIPSAMode* amPC,
                                      MIPSCondCode cond, Bool toFastEP);
index 56481d18e508ad952bd5d7376d78d231f40f31e1..4bc2242fff7df4f79a89418784b539bb05ed7f2b 100644 (file)
@@ -362,7 +362,7 @@ static HReg mk_LoadRR32toFPR(ISelEnv * env, HReg r_srcHi, HReg r_srcLo)
    call is unconditional. */
 
 static void doHelperCall(ISelEnv * env, Bool passBBP, IRExpr * guard,
-                         IRCallee * cee, IRExpr ** args)
+                         IRCallee * cee, IRExpr ** args, RetLoc rloc)
 {
    MIPSCondCode cc;
    HReg argregs[MIPS_N_REGPARMS];
@@ -526,13 +526,13 @@ static void doHelperCall(ISelEnv * env, Bool passBBP, IRExpr * guard,
    /* Finally, the call itself. */
    if (mode64)
       if (cc == MIPScc_AL) {
-         addInstr(env, MIPSInstr_CallAlways(cc, target, argiregs));
+         addInstr(env, MIPSInstr_CallAlways(cc, target, argiregs, rloc));
       } else {
-         addInstr(env, MIPSInstr_Call(cc, target, argiregs, src));
+         addInstr(env, MIPSInstr_Call(cc, target, argiregs, src, rloc));
    } else if (cc == MIPScc_AL) {
-      addInstr(env, MIPSInstr_CallAlways(cc, (Addr32) target, argiregs));
+      addInstr(env, MIPSInstr_CallAlways(cc, (Addr32) target, argiregs, rloc));
    } else {
-      addInstr(env, MIPSInstr_Call(cc, (Addr32) target, argiregs, src));
+      addInstr(env, MIPSInstr_Call(cc, (Addr32) target, argiregs, src, rloc));
    }
    /* restore GuestStatePointer */
    addInstr(env, MIPSInstr_Load(4, GuestStatePointer(mode64),
@@ -1485,13 +1485,26 @@ static HReg iselWordExpr_R_wrk(ISelEnv * env, IRExpr * e)
       HReg r_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 && !mode64)
          goto irreducible;
 
+      /* What's the retloc? */
+      RetLoc rloc = RetLocINVALID;
+      if (ty == Ity_I32) {
+         rloc = RetLocInt;
+      } 
+      else if (ty == Ity_I64) {
+         rloc = mode64 ? RetLocInt : RetLoc2Int;
+      }
+      else {
+         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, rloc);
       addInstr(env, mk_iMOVds_RR(r_dst, hregMIPS_GPR2(mode64)));
       return r_dst;
    }
@@ -2895,23 +2908,47 @@ 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;
 
          if (d->nFxState == 0)
             vassert(!d->needsBBP);
+
          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 = mode64 ? RetLocInt : 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 && !mode64) {
             HReg rHi = newVRegI(env);
             HReg rLo = newVRegI(env);