diff --git a/ChangeLog b/ChangeLog index d5a24a98e..1acc32fa4 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,13 @@ +2014-06-03 Paulo Andrade + + * include/lightning.h, lib/lightning.c: Add the new + jit_indirect() call, that returns a special label node, + and tells lightning that the label may be the target of + an indirect jump. + + * doc/body.texi: Document the new jit_indirect() call, and + add examples of different ways to create labels and branches. + 2014-23-02 Paulo Andrade * lib/jit_x86.c: Rewrite previous patch to inline save/restore diff --git a/doc/body.texi b/doc/body.texi index 91ce9d744..ab75f75b3 100644 --- a/doc/body.texi +++ b/doc/body.texi @@ -22,7 +22,7 @@ both retargetable and very fast. @menu * Overview:: What GNU lightning is * Installation:: Configuring and installing GNU lightning -* The instruction set:: The RISC instruction set used i GNU lightning +* 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 * Acknowledgements:: Acknowledgements for GNU lightning @@ -501,6 +501,66 @@ Like branch instruction, @code{jmpi} also returns a value which is to be used to compile forward branches. @xref{Fibonacci, , Fibonacci numbers}. +@item Labels +There are 3 @lightning{} instructions to create labels: +@example +label (not specified) @r{simple label} +forward (not specified) @r{forward label} +indirect (not specified) @r{special simple label} +@end example + +@code{label} is normally used as @code{patch_at} argument for backward +jumps. + +@example + jit_node_t *jump, *label; +label = jit_label(); + ... + jump = jit_beqr(JIT_R0, JIT_R1); + jit_patch_at(jump, label); +@end example + +@code{forward} is used to patch code generation before the actual +position of the label is known. + +@example + jit_node_t *jump, *label; +label = jit_forward(); + jump = jit_beqr(JIT_R0, JIT_R1); + jit_patch_at(jump, label); + ... + jit_link(label); +@end example + +@code{indirect} is useful when creating jump tables, and tells +@lightning{} to not optimize out a label that is not the target of +any jump, because an indirect jump may land where it is defined. + +@example + jit_node_t *jump, *label; + ... + jmpr(JIT_R0); @rem{/* may jump to label */} + ... +label = jit_indirect(); +@end example + +@code{indirect} is an special case of @code{note} and @code{name} +because it is a valid argument to @code{address}. + +Note that the usual idiom to write the previous example is +@example + jit_node_t *addr, *jump; +addr = jit_movi(JIT_R0, 0); @rem{/* immediate is ignored */} + ... + jmpr(JIT_R0); + ... + jit_patch(addr); @rem{/* implicit label added */} +@end example + +that automatically binds the implicit label added by @code{patch} with +the @code{movi}, but on some special conditions it is required to create +an "unbound" label. + @item Function prolog These macros are used to set up a function prolog. The @code{allocai} diff --git a/include/lightning.h b/include/lightning.h index 9fab1386f..758f76088 100644 --- a/include/lightning.h +++ b/include/lightning.h @@ -174,6 +174,7 @@ typedef enum { #define jit_note(u, v) _jit_note(_jit, u, v) #define jit_label() _jit_label(_jit) #define jit_forward() _jit_forward(_jit) +#define jit_indirect() _jit_indirect(_jit) #define jit_link(u) _jit_link(_jit,u) jit_code_note, jit_code_label, @@ -841,6 +842,7 @@ extern jit_node_t *_jit_name(jit_state_t*, char*); extern jit_node_t *_jit_note(jit_state_t*, char*, int); extern jit_node_t *_jit_label(jit_state_t*); extern jit_node_t *_jit_forward(jit_state_t*); +extern jit_node_t *_jit_indirect(jit_state_t*); extern void _jit_link(jit_state_t*, jit_node_t*); extern void _jit_prolog(jit_state_t*); diff --git a/lib/lightning.c b/lib/lightning.c index de93e9fc5..e0adeda79 100644 --- a/lib/lightning.c +++ b/lib/lightning.c @@ -548,7 +548,10 @@ _jit_address(jit_state_t *_jit, jit_node_t *node) { assert(_jitc->done); assert(node && - (node->code == jit_code_note || node->code == jit_code_name)); + /* If a node type that is documented to be a fixed marker */ + (node->code == jit_code_note || node->code == jit_code_name || + /* If another special fixed marker, returned by jit_indirect() */ + (node->code == jit_code_label && (node->flag & jit_flag_use)))); return ((jit_pointer_t)node->u.w); } @@ -1083,6 +1086,17 @@ _jit_forward(jit_state_t *_jit) return (jit_new_node_no_link(jit_code_label)); } +jit_node_t * +_jit_indirect(jit_state_t *_jit) +{ + jit_node_t *node; + + node = jit_label(); + node->flag |= jit_flag_use; + + return (node); +} + void _jit_link(jit_state_t *_jit, jit_node_t *node) {