Stream: cranelift

Topic: Passing F64 to a C function


view this post on Zulip osa1 (May 15 2020 at 22:43):

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)

view this post on Zulip Dan Gohman (May 15 2020 at 22:46):

To printf a double, use plain %f

view this post on Zulip Dan Gohman (May 15 2020 at 22:47):

(printf is varargs, and in varargs, floats are always promoted to double, so C uses the same format specifiers for float and double)

view this post on Zulip osa1 (May 15 2020 at 22:47):

OK thanks. That doesn't solve the issue though, it still prints 123.000000

view this post on Zulip osa1 (May 15 2020 at 22:48):

I don't really care about the printf line, that's for debugging. The real problem is that the return value is not correct.

view this post on Zulip Dan Gohman (May 15 2020 at 22:49):

0x1.ec00000000000p6 is 123.000000

view this post on Zulip osa1 (May 15 2020 at 22:51):

Ahh.. hmm... I'm using f64const with a Rust f64 value which has the correct value. Out of curiosity how did you check that?

view this post on Zulip Dan Gohman (May 15 2020 at 22:52):

the p6 means "times 2**6" or "times 64", and 1.ec is somewhere between 1 and 2, closer to 2

view this post on Zulip Dan Gohman (May 15 2020 at 22:53):

On Linux, you can use the printf command at the command-line too; printf "%f" 0x1.ec00000000000p prints the result

view this post on Zulip Dan Gohman (May 15 2020 at 22:53):

or you can write a C program that does that

view this post on Zulip osa1 (May 15 2020 at 22:53):

Thanks for the help. I think I found the problem.


Last updated: Dec 23 2024 at 12:05 UTC