| 1 | #include <stdio.h> |
| 2 | #include <lightning.h> |
| 3 | |
| 4 | static jit_state_t *_jit; |
| 5 | |
| 6 | typedef long (*pwfw_t)(long); /* Pointer to Long Function of Long */ |
| 7 | |
| 8 | int main(int argc, char *argv[]) |
| 9 | { |
| 10 | pwfw_t factorial; |
| 11 | long arg; |
| 12 | jit_node_t *ac; /* Accumulator */ |
| 13 | jit_node_t *in; /* Argument */ |
| 14 | jit_node_t *call; |
| 15 | jit_node_t *fact; |
| 16 | jit_node_t *jump; |
| 17 | jit_node_t *fact_entry; |
| 18 | jit_node_t *fact_out; |
| 19 | |
| 20 | init_jit(argv[0]); |
| 21 | _jit = jit_new_state(); |
| 22 | |
| 23 | /* declare a forward label */ |
| 24 | fact = jit_forward(); |
| 25 | |
| 26 | jit_prolog(); /* Entry point of the factorial function */ |
| 27 | in = jit_arg(); /* Receive an integer argument */ |
| 28 | jit_getarg(JIT_R0, in); /* Move argument to RO */ |
| 29 | jit_prepare(); |
| 30 | jit_pushargi(1); /* This is the accumulator */ |
| 31 | jit_pushargr(JIT_R0); /* This is the argument */ |
| 32 | call = jit_finishi(NULL); /* Call the tail call optimized function */ |
| 33 | jit_patch_at(call, fact); /* Patch call to forward defined function */ |
| 34 | /* the above could have been written as: |
| 35 | * jit_patch_at(jit_finishi(NULL), fact); |
| 36 | */ |
| 37 | jit_retval(JIT_R0); /* Fetch the result */ |
| 38 | jit_retr(JIT_R0); /* Return it */ |
| 39 | jit_epilog(); /* Epilog *before* label before prolog */ |
| 40 | |
| 41 | /* define the forward label */ |
| 42 | jit_link(fact); /* Entry point of the helper function */ |
| 43 | jit_prolog(); |
| 44 | jit_frame(16); /* Reserve 16 bytes in the stack */ |
| 45 | fact_entry = jit_label(); /* This is the tail call entry point */ |
| 46 | ac = jit_arg(); /* The accumulator is the first argument */ |
| 47 | in = jit_arg(); /* The factorial argument */ |
| 48 | jit_getarg(JIT_R0, ac); /* Move the accumulator to R0 */ |
| 49 | jit_getarg(JIT_R1, in); /* Move the argument to R1 */ |
| 50 | fact_out = jit_blei(JIT_R1, 1); /* Done if argument is one or less */ |
| 51 | jit_mulr(JIT_R0, JIT_R0, JIT_R1); /* accumulator *= argument */ |
| 52 | jit_putargr(JIT_R0, ac); /* Update the accumulator */ |
| 53 | jit_subi(JIT_R1, JIT_R1, 1); /* argument -= 1 */ |
| 54 | jit_putargr(JIT_R1, in); /* Update the argument */ |
| 55 | jump = jit_jmpi(); |
| 56 | jit_patch_at(jump, fact_entry); /* Tail Call Optimize it! */ |
| 57 | jit_patch(fact_out); |
| 58 | jit_retr(JIT_R0); /* Return the accumulator */ |
| 59 | |
| 60 | factorial = jit_emit(); |
| 61 | /* no need to query information about resolved addresses */ |
| 62 | jit_clear_state(); |
| 63 | |
| 64 | if (argc == 2) |
| 65 | arg = atoi(argv[1]); |
| 66 | else |
| 67 | arg = 5; |
| 68 | |
| 69 | /* call the generated code */ |
| 70 | printf("factorial(%ld) = %ld\n", arg, factorial(arg)); |
| 71 | /* release all memory associated with the _jit identifier */ |
| 72 | jit_destroy_state(); |
| 73 | finish_jit(); |
| 74 | return 0; |
| 75 | } |