[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [Lightning] How to return a floating point value from a function ?
From: |
Paulo César Pereira de Andrade |
Subject: |
Re: [Lightning] How to return a floating point value from a function ? |
Date: |
Fri, 4 Apr 2014 19:04:07 -0300 |
2014-04-04 17:12 GMT-03:00 Domingo Alvarez Duarte <address@hidden>:
> Hello !
Hi,
> I was looking on the docs and web but did not found an example explanation
> of how to return floating points from lightning generated functions, so I'm
> asking here to see if someone can help me, also this can be added to the
> documentation to make it easy for others.
I think documentation is indeed not very clear about this, or there are
not enough, and well documented examples. I will comment below your
sample code the problems.
> Here is a example that I'm trying to create with lightning, the integer
> functions works as expected but the floating pointing ones doesn't.
>
> Thanks in advance for any help !
>
> -----
> #include <stdio.h>
> #include <lightning.h>
>
> //static jit_state_t *_jit;
>
> int inative_mult(int a, int b) {
> return a * b;
> }
>
> int inative_div(int a, int b) {
> return a / b;
> }
>
> typedef int (*pifii)(int, int); /* Pointer to Int Function of Int Int */
>
> double dnative_mult(double a, double b) {
> return a * b;
> }
>
> double dnative_div(double a, double b) {
> return a / b;
> }
>
> typedef double (*pdfdd)(double, double); /* Pointer to double Function of
> double double */
>
> int main(int argc, char *argv[])
> {
> jit_state_t *_jit;
> pifii imyMult, imyDiv; /* ptr to generated code */
> jit_node_t *startIMult, *startIDiv; /* a couple of labels */
>
> pdfdd dmyMult, dmyDiv; /* ptr to generated code */
> jit_node_t *startDMult, *startDDiv; /* a couple of labels */
>
> jit_node_t *inA, *inB; /* to get the argument */
>
> init_jit(argv[0]);
> _jit = jit_new_state();
>
> startIMult = jit_note(__FILE__, __LINE__);
> jit_prolog();
> inA = jit_arg();
> inB = jit_arg();
> jit_getarg(JIT_V0, inA);
> jit_getarg(JIT_V1, inB);
> jit_mulr(JIT_R0, JIT_V0, JIT_V1);
> jit_ret();
You should use "jit_retr(JIT_R0);" instead of "jit_ret();". Plain
jit_ret() should be used for void functions. It is working because
the return register maps to JIT_R0 on *most* lightning ports,
but not all.
> jit_epilog();
>
> startIDiv = jit_note(__FILE__, __LINE__);
> jit_prolog();
> inA = jit_arg();
> inB = jit_arg();
> jit_getarg(JIT_V0, inA);
> jit_getarg(JIT_V1, inB);
> jit_divr(JIT_R0, JIT_V0, JIT_V1);
> jit_ret();
Same problem with jit_ret(), where should use jit_retr(JIT_R0)
> jit_epilog();
>
> startDMult = jit_note(__FILE__, __LINE__);
> jit_prolog();
> inA = jit_arg_f();
> inB = jit_arg_f();
> jit_getarg_f(JIT_F0, inA);
> jit_getarg_f(JIT_F1, inB);
> jit_mulr_f(JIT_FA0, JIT_F0, JIT_F1);
> jit_retr_f(JIT_FA0);
Well, it was a mistake to export the JIT_FA0 symbol :-) Please
do not use it. It is only available on a few ports, where float/double
arguments are passed on registers, and is an alias for the
first argument register. I suggest writing:
jit_mulr_f(JIT_F0, JIT_F0, JIT_F1);
jit_retr_f(JIT_F0);
it is actually better this way for ix86, x86_64 and s390 that have
two operand instructions.
> jit_epilog();
>
> startDDiv = jit_note(__FILE__, __LINE__);
> jit_prolog();
> inA = jit_arg_f();
> inB = jit_arg_f();
> jit_getarg_f(JIT_F0, inA);
> jit_getarg_f(JIT_F1, inB);
> jit_divr_f(JIT_FA0, JIT_F0, JIT_F1);
> jit_retr_f(JIT_FA0);
Same comment about not using JIT_FA0.
> jit_epilog();
>
> jit_emit();
>
> imyMult = (pifii)jit_address(startIMult);
> imyDiv = (pifii)jit_address(startIDiv);
>
> dmyMult = (pdfdd)jit_address(startDMult);
> dmyDiv = (pdfdd)jit_address(startDDiv);
This is bad, you are casting float (*)(float,float) to double
(*)(double, double)
> jit_clear_state();
>
> /* call the generated code, passing its size as argument */
> printf("jit_native_imult(%d, %d) = %d\n", 12, 27, imyMult(12, 27));
> printf("jit_native_idiv(%d, %d) = %d\n", 27, 12, imyDiv(27, 12));
>
> printf("jit_native_dmult(%f, %f) = %f\n", 12.3, 27.5, dmyMult(12.3,
> 27.5));
> printf("jit_native_ddiv(%f, %f) = %f\n", 27.5, 12.3, dmyDiv(27.5, 12.3));
You should either change the functions to operate on doubles, or use
the proper cast so that the compiler would convert the float return to
a double, as printf only accepts doubles. So, either:
-typedef double (*pdfdd)(double, double); /* Pointer to double
Function of double double */
+typedef float (*pdfdd)(float, float); /* Pointer to double
Function of double double */
or a global "s/_f/_d/g" in the sample source.
> jit_disassemble();
>
> jit_destroy_state();
> finish_jit();
> return 0;
> }
Thanks,
Paulo