| [ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
printf Again, here is the code for the example:
#include <stdio.h>
#include "lightning.h"
static jit_insn codeBuffer[1024];
typedef void (*pvfi)(int); /* Pointer to Void Function of Int */
int main()
{
pvfi myFunction; /* ptr to generated code */
char *start, *end; /* a couple of labels */
int in; /* to get the argument */
myFunction = (pvfi) (jit_set_ip(codeBuffer).vptr);
start = jit_get_ip().ptr;
jit_prolog(1);
in = jit_arg_i();
jit_movi_p(JIT_R0, "generated %d bytes\n");
jit_getarg_i(JIT_R1, in);
jit_prepare(2);
jit_pusharg_i(JIT_R1); /* push in reverse order */
jit_pusharg_p(JIT_R0);
jit_finish(printf);
jit_ret();
end = jit_get_ip().ptr;
/* call the generated code, passing its size as argument */
jit_flush_code(start, end);
myFunction(end - start);
}
|
The function shows how many bytes were generated. Most of the code is not very interesting, as it resembles very closely the program presented in A function which increments a number by one.
For this reason, we're going to concentrate on just a few statements.
jit_get_ip macro which was
mentioned in A function which increments a number by one
too. In this case we use the only field of jit_code that is
not a function pointer: ptr, which is a simple char *.
unsigned long to make the
code more clear and less cluttered by typecasts.
printf have been put in general-purpose
registers, we can start a prepare/pusharg/finish sequence that
moves the argument to either the stack or registers, then calls
printf, then cleans up the stack. Note how GNU lightning
abstracts the differences between different architectures and
ABI's -- the client program does not know how parameter passing
works on the host architecture.
| [ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |