123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142 |
- #include <stdlib.h>
- #include <stdio.h>
- #include "libgccjit.h"
- #include "harness.h"
- /* A doubly-linked list, to ensure that the JIT API can cope with
- self-referential types. */
- struct node
- {
- struct node *prev;
- struct node *next;
- int value;
- };
- void
- create_code (gcc_jit_context *ctxt, void *user_data)
- {
- /* Let's try to inject the equivalent of:
- int
- test_linked_list (struct node *n)
- {
- int total = 0;
- while (n)
- {
- total += n->value;
- n = n->next;
- }
- return total;
- }
- */
- gcc_jit_type *t_int =
- gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_INT);
- gcc_jit_struct *t_node =
- gcc_jit_context_new_opaque_struct (ctxt, NULL, "node");
- gcc_jit_type *t_node_ptr =
- gcc_jit_type_get_pointer (gcc_jit_struct_as_type (t_node));
- gcc_jit_field *f_prev =
- gcc_jit_context_new_field (ctxt, NULL, t_node_ptr, "prev");
- gcc_jit_field *f_next =
- gcc_jit_context_new_field (ctxt, NULL, t_node_ptr, "next");
- gcc_jit_field *f_value =
- gcc_jit_context_new_field (ctxt, NULL, t_int, "value");
- gcc_jit_field *fields[] = {f_prev, f_next, f_value};
- gcc_jit_struct_set_fields (t_node, NULL, 3, fields);
- /* Build the test function. */
- gcc_jit_param *param_n =
- gcc_jit_context_new_param (ctxt, NULL, t_node_ptr, "n");
- gcc_jit_function *fn =
- gcc_jit_context_new_function (ctxt, NULL,
- GCC_JIT_FUNCTION_EXPORTED,
- t_int,
- "test_linked_list",
- 1, ¶m_n,
- 0);
- /* int total; */
- gcc_jit_lvalue *total =
- gcc_jit_function_new_local (fn, NULL, t_int, "total");
- gcc_jit_block *initial = gcc_jit_function_new_block (fn, "initial");
- gcc_jit_block *loop_test = gcc_jit_function_new_block (fn, "loop_test");
- gcc_jit_block *loop_body = gcc_jit_function_new_block (fn, "loop_body");
- gcc_jit_block *final = gcc_jit_function_new_block (fn, "final");
- /* total = 0; */
- gcc_jit_block_add_assignment (
- initial, NULL,
- total,
- gcc_jit_context_zero (ctxt, t_int));
- gcc_jit_block_end_with_jump (initial, NULL, loop_test);
- /* while (n) */
- gcc_jit_block_end_with_conditional (
- loop_test, NULL,
- gcc_jit_context_new_comparison (ctxt, NULL,
- GCC_JIT_COMPARISON_NE,
- gcc_jit_param_as_rvalue (param_n),
- gcc_jit_context_null (ctxt, t_node_ptr)),
- loop_body,
- final);
- /* total += n->value; */
- gcc_jit_block_add_assignment_op (
- loop_body, NULL,
- total,
- GCC_JIT_BINARY_OP_PLUS,
- gcc_jit_lvalue_as_rvalue (
- gcc_jit_rvalue_dereference_field (
- gcc_jit_param_as_rvalue (param_n),
- NULL,
- f_value)));
- /* n = n->next; */
- gcc_jit_block_add_assignment (
- loop_body, NULL,
- gcc_jit_param_as_lvalue (param_n),
- gcc_jit_lvalue_as_rvalue (
- gcc_jit_rvalue_dereference_field (
- gcc_jit_param_as_rvalue (param_n),
- NULL,
- f_next)));
- gcc_jit_block_end_with_jump (loop_body, NULL, loop_test);
- /* return total; */
- gcc_jit_block_end_with_return (
- final, NULL, gcc_jit_lvalue_as_rvalue (total));
- }
- void
- verify_code (gcc_jit_context *ctxt, gcc_jit_result *result)
- {
- struct node a, b, c;
- typedef int (*fn_type) (struct node *n);
- CHECK_NON_NULL (result);
- fn_type test_linked_list =
- (fn_type)gcc_jit_result_get_code (result, "test_linked_list");
- CHECK_NON_NULL (test_linked_list);
- /* Construct a simple linked-list on the stack: a->b->c: */
- a.prev = NULL;
- a.next = &b;
- a.value = 5;
- b.prev = &a;
- b.next = &c;
- b.value = 3;
- c.prev = &b;
- c.next = NULL;
- c.value = 7;
- CHECK_VALUE (test_linked_list (NULL), 0);
- CHECK_VALUE (test_linked_list (&a), 15);
- CHECK_VALUE (test_linked_list (&b), 10);
- CHECK_VALUE (test_linked_list (&c), 7);
- }
|