I'm generating a function call where the function's sig is
Signature { params: [AbiParam { value_type: types::I64, purpose: Normal, extension: None, location: Unassigned }, AbiParam { value_type: types::F64, purpose: Normal, extension: None, location: Unassigned }], returns: [AbiParam { value_type: types::I64, purpose: Normal, extension: None, location: Unassigned }], call_conv: SystemV }
or simply, (I64, F64) -> I64
. The function is defined like this in C:
int64_t mc_int_of_float_f(FunctionClosure *self, double d) {
printf("%lf\n", (float)d);
return (int64_t)llround(d);
}
I checked and double
is 8-bytes on my system.
For some reason when I pass 1.23 to this function the print line prints 123.000000
. Any ideas what I'm doing wrong?
Relevant code that does the call:
v0 = f64const 0x1.ec00000000000p6
v1 = global_value.i64 gv0
v2 = load.i64 v1
v3 = global_value.i64 gv1
v4 = call_indirect sig1, v2(v3, v0)
To printf a double, use plain %f
(printf is varargs, and in varargs, floats are always promoted to double, so C uses the same format specifiers for float and double)
OK thanks. That doesn't solve the issue though, it still prints 123.000000
I don't really care about the printf line, that's for debugging. The real problem is that the return value is not correct.
0x1.ec00000000000p6 is 123.000000
Ahh.. hmm... I'm using f64const
with a Rust f64
value which has the correct value. Out of curiosity how did you check that?
the p6
means "times 2**6" or "times 64", and 1.ec is somewhere between 1 and 2, closer to 2
On Linux, you can use the printf command at the command-line too; printf "%f" 0x1.ec00000000000p
prints the result
or you can write a C program that does that
Thanks for the help. I think I found the problem.
Last updated: Dec 23 2024 at 12:05 UTC