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 */