The arguments in a helper call need to be sign/zero-extended
to 64 bit. Fix helper calls accordingly. And because I keep forgetting
this, add checking machinery in the insn selector so it won't happen again.
Diagnosed by Christian Borntraeger.


git-svn-id: svn://svn.valgrind.org/vex/trunk@2462 8f6e269a-dfd6-0310-a8e1-e2731360e62c
diff --git a/priv/guest_s390_toIR.c b/priv/guest_s390_toIR.c
index 188992f..334287f 100644
--- a/priv/guest_s390_toIR.c
+++ b/priv/guest_s390_toIR.c
@@ -10685,7 +10685,7 @@
 static HChar *
 s390_irgen_CVD(UChar r1, IRTemp op2addr)
 {
-   store(mkexpr(op2addr), s390_call_cvd(get_gpr_w1(r1)));
+   store(mkexpr(op2addr), s390_call_cvd(unop(Iop_32Uto64, get_gpr_w1(r1))));
 
    return "cvd";
 }
@@ -11212,7 +11212,8 @@
 
    /* Call the helper */
    IRTemp retval = newTemp(Ity_I64);
-   assign(retval, s390_call_cu21(mkexpr(srcval), mkexpr(low_surrogate)));
+   assign(retval, s390_call_cu21(unop(Iop_32Uto64, mkexpr(srcval)),
+                                 unop(Iop_32Uto64, mkexpr(low_surrogate))));
 
    /* Before we can test whether the 1st operand is exhausted we need to
       test for an invalid low surrogate. Because cc=2 outranks cc=1. */
@@ -11339,7 +11340,8 @@
 
    /* Call the helper */
    IRTemp retval = newTemp(Ity_I64);
-   assign(retval, s390_call_cu24(mkexpr(srcval), mkexpr(low_surrogate)));
+   assign(retval, s390_call_cu24(unop(Iop_32Uto64, mkexpr(srcval)),
+                                 unop(Iop_32Uto64, mkexpr(low_surrogate))));
 
    /* Before we can test whether the 1st operand is exhausted we need to
       test for an invalid low surrogate. Because cc=2 outranks cc=1. */
@@ -11416,7 +11418,7 @@
 
    /* Call the helper */
    IRTemp retval = newTemp(Ity_I64);
-   assign(retval, s390_call_cu42(mkexpr(srcval)));
+   assign(retval, s390_call_cu42(unop(Iop_32Uto64, mkexpr(srcval))));
 
    /* If the UTF-32 character was invalid, set cc=2 and we're done.
       cc=2 outranks cc=1 (1st operand exhausted) */
@@ -11510,7 +11512,7 @@
 
    /* Call the helper */
    IRTemp retval = newTemp(Ity_I64);
-   assign(retval, s390_call_cu41(mkexpr(srcval)));
+   assign(retval, s390_call_cu41(unop(Iop_32Uto64, mkexpr(srcval))));
 
    /* If the UTF-32 character was invalid, set cc=2 and we're done.
       cc=2 outranks cc=1 (1st operand exhausted) */
@@ -11628,13 +11630,13 @@
    next_insn_if(binop(Iop_CmpLT64U, mkexpr(len2), mkU64(1)));
 
    /* There is at least one byte there. Read it. */
-   IRTemp byte1 = newTemp(Ity_I32);
-   assign(byte1, unop(Iop_8Uto32, load(Ity_I8, mkexpr(addr2))));
+   IRTemp byte1 = newTemp(Ity_I64);
+   assign(byte1, unop(Iop_8Uto64, load(Ity_I8, mkexpr(addr2))));
 
    /* Call the helper to get number of bytes and invalid byte indicator */
    IRTemp retval1 = newTemp(Ity_I64);
    assign(retval1, s390_call_cu12_cu14_helper1(mkexpr(byte1),
-                                               mkU32(extended_checking)));
+                                               mkU64(extended_checking)));
 
    /* Check for invalid 1st byte */
    IRExpr *is_invalid = unop(Iop_64to1, mkexpr(retval1));
@@ -11654,13 +11656,13 @@
 
    cond  = binop(Iop_CmpLE64U, mkU64(2), mkexpr(num_src_bytes));
    addr  = binop(Iop_Add64, mkexpr(addr2), mkU64(1));
-   byte2 = mkite(cond, unop(Iop_8Uto32, load(Ity_I8, addr)), mkU32(0));
+   byte2 = mkite(cond, unop(Iop_8Uto64, load(Ity_I8, addr)), mkU64(0));
    cond  = binop(Iop_CmpLE64U, mkU64(3), mkexpr(num_src_bytes));
    addr  = binop(Iop_Add64, mkexpr(addr2), mkU64(2));
-   byte3 = mkite(cond, unop(Iop_8Uto32, load(Ity_I8, addr)), mkU32(0));
+   byte3 = mkite(cond, unop(Iop_8Uto64, load(Ity_I8, addr)), mkU64(0));
    cond  = binop(Iop_CmpLE64U, mkU64(4), mkexpr(num_src_bytes));
    addr  = binop(Iop_Add64, mkexpr(addr2), mkU64(3));
-   byte4 = mkite(cond, unop(Iop_8Uto32, load(Ity_I8, addr)), mkU32(0));
+   byte4 = mkite(cond, unop(Iop_8Uto64, load(Ity_I8, addr)), mkU64(0));
 
    /* Call the helper to get the converted value and invalid byte indicator.
       We can pass at most 5 arguments; therefore some encoding is needed
diff --git a/priv/host_s390_isel.c b/priv/host_s390_isel.c
index 565111a..8ac425a 100644
--- a/priv/host_s390_isel.c
+++ b/priv/host_s390_isel.c
@@ -465,6 +465,25 @@
       vpanic("doHelperCall: too many arguments");
    }
 
+   /* All arguments must have Ity_I64. For two reasons:
+      (1) We do not handle floating point arguments.
+      (2) The ABI requires that integer values are sign- or zero-extended
+           to 64 bit.
+   */
+   Int arg_errors = 0;
+   for (i = 0; i < n_args; ++i) {
+      IRType type = typeOfIRExpr(env->type_env, args[i]);
+      if (type != Ity_I64) {
+         ++arg_errors;
+         vex_printf("calling %s: argument #%d has type ", callee->name, i);
+         ppIRType(type);
+         vex_printf("; Ity_I64 is required\n");
+      }
+   }
+
+   if (arg_errors)
+      vpanic("cannot continue due to errors in argument passing");
+
    argreg = 0;
 
    /* If we need the guest state pointer put it in a temporary arg reg */