lightning
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Lightning] JIT_R11 trashed by jit_callr on MIPS32


From: Paulo César Pereira de Andrade
Subject: Re: [Lightning] JIT_R11 trashed by jit_callr on MIPS32
Date: Wed, 29 Oct 2014 22:40:23 -0200

2014-10-29 19:49 GMT-02:00 Paul Cercueil <address@hidden>:
> Hi,

  Hi,

>>    This should be what you need to make it fully portable, and remove
>> most if not all overhead:
>>
>> http://git.savannah.gnu.org/cgit/lightning.git/commit/?id=839341a498b7b2077d715c2ca66d3debcddc0c30
>>
>>    I am delaying a bit release of lightning 2.0.6, as I hope to fix any
>> possible issue with the GNU Smalltalk port to use it, but if you
>> could test the current git, I would really appreciate, and jit_frame
>> and jit_tramp may be exactly what you need.
>
>
> From a quick look it looks exactly what I need, yes. Thanks a lot!
> But I can't build from the GIT, there's no ./configure and no m4 files to
> build it using autoconf, what am I missing?

  You should run something like:

$ mkdir m4; autoreconf -ifs

>>    Note that if you do the current approach, you are risking to have
>> your code only working on a few (register rich) lightning backends,
>> and will break on newer lightning, because (the undocumented)
>> JIT_RA0 was removed, to avoid it being used, and writing non
>> portable code :(
>>
>>    Basically, the new interfaces are like this:
>>
>> jit_prolog();
>> jit_tramp(256);
>> ...
>> jit_epilog();
>>
>> saves all callee save registers, creates a stack frame of 256
>> bytes for any arguments on stack or jit_allocai calls. And:
>>
>> jit_prolog();
>> jit_tramp(256);
>> ...
>> jit_epilog();
>>
>> assumes the the prolog/epilog and frame. You must write code
>> that jumps and return from there, that is, you can actually write
>> the function body later.
>
>
> I assume you meant jit_frame(256) on the former - but I get the idea.

  Yes, sorry, the first one is jit_frame(256).

> Is that stack area also used for parameter passing on x86, or just to save a
> snapshot of the register set?

  The programmer should only care about memory used for parameter
passing and allocai, everything else is handled by lightning. If you are
sure about alignment, types and architecture, may use less bytes, but
to make sure, a good formula is "nargs * 8 + allocai", where nargs is
the maximum number of arguments the generated code will pass to
a function.

  From what I understand of your usage, lightning could have some
optimizations for it. For example:

1. a proper call to sync cache (in my TODO already)
2. a way to reset/reuse a jit_state_t.

  But it would still be not comparable to a "code generator" written
specifically
for retargeting, e.g. qemu.

>>>>   > It abuses Lightning a little bit, in the way that it doesn't use
>>>> functions - the generated code directly jumps to the next block of code,
>>>> recompiling it if needed. It works fine on MIPS32 for now, except for
>>>> one point: jit_callr trashes the JIT_R11 register...
>>>>
>>>>     I am afraid this is expected :(
>>>>
>>>>   > Here's a minimal test case:
>>>>   >
>>>>   > <paul:~/dev/gcw0/lightrec> $ cat minimal.c
>>>>   > #include <lightning.h>
>>>>   >
>>>>   > static void get_new_function(void) { return &end_execution; }
>>>>   >
>>>>   > int main(int argc, char **argv)
>>>>   > {
>>>>   >         jit_state_t *_jit;
>>>>   >         init_jit(argv[0]);
>>>>   >
>>>>   >         _jit = jit_new_state();
>>>>   >
>>>>   >         jit_movi(JIT_R11, 54);
>>>>   >         jit_movi(JIT_R0, &get_new_function);
>>>>   >         jit_callr(JIT_R0);
>>>>   >
>>>>   >         jit_retval(JIT_R0);
>>>>   >         jit_addr(JIT_R0, JIT_R0, JIT_R11);
>>>>   >         jit_jmpr(JIT_R0);
>>>>   >
>>>>   >         jit_emit();
>>>>   >         jit_disassemble();
>>>>   >         jit_clear_state();
>>>>   >         jit_destroy_state();
>>>>   >         finish_jit();
>>>>   >
>>>>   >         return 0;
>>>>   > }
>>>>   >
>>>>   > The code basically sets the JIT_R11 register to 54, call
>>>> "get_new_function", adds JIT_R11 to the value returned and jumps to that
>>>> new address.
>>>>   >
>>>>   > This is what I obtain:
>>>>   >
>>>>   > opendingux:/media/data/local/home # ./minimal
>>>>   >         0x77295000      li      t9,54
>>>>   >         0x77295004      lui     v0,0x40
>>>>   >         0x77295008      ori     v0,v0,0x9d0
>>>>   >         0x7729500c      move    t9,v0
>>>>   >         0x77295010      jalr    v0
>>>>   >         0x77295014      nop
>>>>   >         0x77295018      addu    v0,v0,t9
>>>>   >         0x7729501c      jr      v0
>>>>   >         0x77295020      nop
>>>>   >
>>>>   > The LUI/ORI correspond the load of the address of get_new_function.
>>>> The jalr is the jit_callr. But between those, the JIT_R11 (register $t9
>>>> here) is trashed for no good reason.
>>>>   >
>>>>   > My current workaround is to completely avoid the use of JIT_R11, but
>>>> it would be great if it could be fixed :).
>>>>
>>>>     Remember that JIT_R11 is not callee save, so, lightning is
>>>> supposed to be allowed to clobber it. A backend specific comment
>>>> should be added to the documentation about such special cases.
>>>>
>>>>     t9 is the pic register. Lightning does not know if it is calling a
>>>> pic C function so if the jit_callr argument is not t9, it will set it to
>>>> the function pointer. A workaround in your code would be to
>>>> know about that.
>>>
>>>
>>>
>>> Allright, I didn't know that. I knew about $gp (register #26) but not
>>> about
>>> $t9. Then I guess I will discard it when compiling on MIPS.
>>
>>
>>    It is dangerous to rely on non callee save registers not being
>> clobbered.
>> Even if it is calling a jit function. Alpha uses the pv (r27) register the
>> same
>> way, but the alpha port does not make it, register 27, a "visible"
>> JIT_R(n).
>> PowerPC clobbers r2 and r11, but also on ppc they are not made into
>> a JIT_R(n). Hppa clobbers r1 and r19, again not made into a JIT_R(n).
>> Mips was the first lightning port I made, so, maybe I should change it
>> to not make JIT_R11 available?
>
>
> Well I certainly didn't expect Lightning to use a JIT_R(n) register
> internally. I know that those can be trashed when calling C functions, but I
> assumed that they would never be trashed within the generated code.
>
> I think that it would be better to avoid this problem, yes. JIT_R11 should
> be removed from the list of available registers. It's not a big deal on MIPS
> anyway, there are plenty of registers that can be used there.

  Ok. For consistency with other ports, I will change it to no longer export
it. Just note that is possible to have a setup where an argument register
is also the return register. The most common case is to have JIT_R0 as
the return register, but if the jit code does not return anything, it will not
be clobbered.

Thanks,
Paulo



reply via email to

[Prev in Thread] Current Thread [Next in Thread]