mirror of
https://git.savannah.gnu.org/git/guile.git
synced 2025-05-04 14:20:26 +02:00
Document the lightning customization functions.
* doc/body.texi: Write detailed description and examples for jit_get_memory_functions, jit_set_memory_functions, jit_get_code, jit_set_code, jit_get_data and jit_set_data.
This commit is contained in:
parent
33ee2337c7
commit
a7cde4ba18
2 changed files with 167 additions and 6 deletions
|
@ -1,3 +1,9 @@
|
|||
2014-12-03 Paulo Andrade <pcpa@gnu.org>
|
||||
|
||||
* doc/body.texi: Write detailed description and examples for
|
||||
jit_get_memory_functions, jit_set_memory_functions,
|
||||
jit_get_code, jit_set_code, jit_get_data and jit_set_data.
|
||||
|
||||
2014-12-03 Paulo Andrade <pcpa@gnu.org>
|
||||
|
||||
* include/lightning.h, include/lightning/jit_private.h,
|
||||
|
|
167
doc/body.texi
167
doc/body.texi
|
@ -15,9 +15,7 @@
|
|||
@end ifnottex
|
||||
|
||||
This document describes @value{TOPIC} the @lightning{} library for
|
||||
dynamic code generation. Unlike other dynamic code generation systems,
|
||||
which are usually either inefficient or non-portable, @lightning{} is
|
||||
both retargetable and very fast.
|
||||
dynamic code generation.
|
||||
|
||||
@menu
|
||||
* Overview:: What GNU lightning is
|
||||
|
@ -25,6 +23,7 @@ both retargetable and very fast.
|
|||
* The instruction set:: The RISC instruction set used in GNU lightning
|
||||
* GNU lightning examples:: GNU lightning's examples
|
||||
* Reentrancy:: Re-entrant usage of GNU lightning
|
||||
* Customizations:: Advanced code generation customizations
|
||||
* Acknowledgements:: Acknowledgements for GNU lightning
|
||||
@end menu
|
||||
@end ifnottex
|
||||
|
@ -34,9 +33,7 @@ both retargetable and very fast.
|
|||
|
||||
@iftex
|
||||
This document describes @value{TOPIC} the @lightning{} library for
|
||||
dynamic code generation. Unlike other dynamic code generation systems,
|
||||
which are usually either inefficient or non-portable, @lightning{} is
|
||||
both retargetable and very fast.
|
||||
dynamic code generation.
|
||||
@end iftex
|
||||
|
||||
Dynamic code generation is the generation of machine code
|
||||
|
@ -1277,6 +1274,164 @@ constant. Of course, expressions like @code{JIT_R0} and
|
|||
@code{JIT_R(0)} denote the same register, and likewise for
|
||||
integer callee-saved, or floating-point, registers.
|
||||
|
||||
@node Customizations
|
||||
@chapter Customizations
|
||||
|
||||
Frequently it is desirable to have more control over how code is
|
||||
generated or how memory is used during jit generation or execution.
|
||||
|
||||
@section Memory functions
|
||||
To aid in complete control of memory allocation and deallocation
|
||||
@lightning{} provides wrappers that default to standard @code{malloc},
|
||||
@code{realloc} and @code{free}. These are loosely based on the
|
||||
GNU GMP counterparts, with the difference that they use the same
|
||||
prototype of the system allocation functions, that is, no @code{size}
|
||||
for @code{free} or @code{old_size} for @code{realloc}.
|
||||
|
||||
@deftypefun void jit_set_memory_functions (@* void *(*@var{alloc_func_ptr}) (size_t), @* void *(*@var{realloc_func_ptr}) (void *, size_t), @* void (*@var{free_func_ptr}) (void *))
|
||||
@lightning{} guarantees that memory is only allocated or released
|
||||
using these wrapped functions, but you must note that if lightning
|
||||
was linked to GNU binutils, malloc is probably will be called multiple
|
||||
times from there when initializing the disassembler.
|
||||
@end deftypefun
|
||||
|
||||
@deftypefun void jit_get_memory_functions (@* void *(**@var{alloc_func_ptr}) (size_t), @* void *(**@var{realloc_func_ptr}) (void *, size_t), @* void (**@var{free_func_ptr}) (void *))
|
||||
Get the current memory allocation function. Also, unlike the GNU GMP
|
||||
counterpart, it is an error to pass @code{NULL} pointers as arguments.
|
||||
@end deftypefun
|
||||
|
||||
@section Alternate code buffer
|
||||
To instruct @lightning{} to use an alternate code buffer it is required
|
||||
to call @code{jit_realize} before @code{jit_emit}, and then query states
|
||||
and customize as appropriate.
|
||||
|
||||
@deftypefun void jit_realize ()
|
||||
Must be called once, before @code{jit_emit}, to instruct @lightning{}
|
||||
that no other @code{jit_xyz} call will be made.
|
||||
@end deftypefun
|
||||
|
||||
@deftypefun jit_pointer_t jit_get_code (jit_word_t *@var{code_size})
|
||||
Returns NULL or the previous value set with @code{jit_set_code}, and
|
||||
sets the @var{code_size} argument to an appropriate value.
|
||||
If @code{jit_get_code} is called before @code{jit_emit}, the
|
||||
@var{code_size} argument is set to the expected amount of bytes
|
||||
required to generate code.
|
||||
If @code{jit_get_code} is called after @code{jit_emit}, the
|
||||
@var{code_size} argument is set to the exact amount of bytes used
|
||||
by the code.
|
||||
@end deftypefun
|
||||
|
||||
@deftypefun void jit_set_code (jit_ponter_t @var{code}, jit_word_t @var{size})
|
||||
Instructs @lightning{} to output to the @var{code} argument and
|
||||
use @var{size} as a guard to not write to invalid memory. If during
|
||||
@code{jit_emit} @lightning{} finds out that the code would not fit
|
||||
in @var{size} bytes, it halts code emit and returns @code{NULL}.
|
||||
@end deftypefun
|
||||
|
||||
A simple example of a loop using an alternate buffer is:
|
||||
|
||||
@example
|
||||
jit_uint8_t *code;
|
||||
int *(func)(int); @rem{/* function pointer */}
|
||||
jit_word_t code_size;
|
||||
jit_word_t real_code_size;
|
||||
@rem{...}
|
||||
jit_realize(); @rem{/* ready to generate code */}
|
||||
jit_get_code(&code_size); @rem{/* get expected code size */}
|
||||
code_size = (code_size + 4095) & -4096;
|
||||
do (;;) @{
|
||||
code = mmap(NULL, code_size, PROT_EXEC | PROT_READ | PROT_WRITE,
|
||||
MAP_PRIVATE | MAP_ANON, -1, 0);
|
||||
jit_set_code(code, code_size);
|
||||
if ((func = jit_emit()) == NULL) @{
|
||||
munmap(code, code_size);
|
||||
code_size += 4096;
|
||||
@}
|
||||
@} while (func == NULL);
|
||||
jit_get_code(&real_code_size); @rem{/* query exact size of the code */}
|
||||
@end example
|
||||
|
||||
The first call to @code{jit_get_code} should return @code{NULL} and set
|
||||
the @code{code_size} argument to the expected amount of bytes required
|
||||
to emit code.
|
||||
The second call to @code{jit_get_code} is after a successful call to
|
||||
@code{jit_emit}, and will return the value previously set with
|
||||
@code{jit_set_code} and set the @code{real_code_size} argument to the
|
||||
exact amount of bytes used to emit the code.
|
||||
|
||||
@section Alternate data buffer
|
||||
Sometimes it may be desirable to customize how, or to prevent
|
||||
@lightning{} from using an extra buffer for constants or debug
|
||||
annotation. Usually when also using an alternate code buffer.
|
||||
|
||||
@deftypefun jit_pointer_t jit_get_data (jit_word_t *@var{data_size}, jit_word_t *@var{note_size})
|
||||
Returns @code{NULL} or the previous value set with @code{jit_set_data},
|
||||
and sets the @var{data_size} argument to how many bytes are required
|
||||
for the constants data buffer, and @var{note_size} to how many bytes
|
||||
are required to store the debug note information.
|
||||
Note that it always preallocate one debug note entry even if
|
||||
@code{jit_name} or @code{jit_note} are never called, but will return
|
||||
zero in the @var{data_size} argument if no constant is required;
|
||||
constants are only used for the @code{float} and @code{double} operations
|
||||
that have an immediate argument, and not in all @lightning{} ports.
|
||||
@end deftypefun
|
||||
|
||||
@deftypefun void jit_set_data (jit_pointer_t @var{data}, jit_word_t @var{size}, jit_word_t @var{flags})
|
||||
|
||||
@var{data} can be NULL if disabling constants and annotations, otherwise,
|
||||
a valid pointer must be passed. An assertion is done that the data will
|
||||
fit in @var{size} bytes (but that is a noop if @lightning{} was built
|
||||
with @code{-DNDEBUG}).
|
||||
|
||||
@var{size} tells the space in bytes available in @var{data}.
|
||||
|
||||
@var{flags} can be zero to tell to just use the alternate data buffer,
|
||||
or a composition of @code{JIT_DISABLE_DATA} and @code{JIT_DISABLE_NOTE}
|
||||
|
||||
@table @t
|
||||
@item JIT_DISABLE_DATA
|
||||
@cindex JIT_DISABLE_DATA
|
||||
Instructs @lightning{} to not use a constant table, but to use an
|
||||
alternate method to synthesize those, usually with a larger code
|
||||
sequence using stack space to transfer the value from a GPR to a
|
||||
FPR register.
|
||||
|
||||
@item JIT_DISABLE_NOTE
|
||||
@cindex JIT_DISABLE_NOTE
|
||||
Instructs @lightning{} to not store file or function name, and
|
||||
line numbers in the constant buffer.
|
||||
@end table
|
||||
@end deftypefun
|
||||
|
||||
A simple example of a preventing usage of a data buffer is:
|
||||
|
||||
@example
|
||||
@rem{...}
|
||||
jit_realize(); @rem{/* ready to generate code */}
|
||||
jit_get_data(NULL, NULL);
|
||||
jit_set_data(NULL, 0, JIT_DISABLE_DATA | JIT_DISABLE_NOTE);
|
||||
@rem{...}
|
||||
@end example
|
||||
|
||||
Or to only use a data buffer, if required:
|
||||
|
||||
@example
|
||||
jit_uint8_t *data;
|
||||
jit_word_t data_size;
|
||||
@rem{...}
|
||||
jit_realize(); @rem{/* ready to generate code */}
|
||||
jit_get_data(&data_size, NULL);
|
||||
if (data_size)
|
||||
data = malloc(data_size);
|
||||
else
|
||||
data = NULL;
|
||||
jit_set_data(data, data_size, JIT_DISABLE_NOTE);
|
||||
@rem{...}
|
||||
if (data)
|
||||
free(data);
|
||||
@rem{...}
|
||||
@end example
|
||||
|
||||
@node Acknowledgements
|
||||
@chapter Acknowledgements
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue