diff options
Diffstat (limited to 'gcc/testsuite/jit.dg/test-linked-list.c')
-rw-r--r-- | gcc/testsuite/jit.dg/test-linked-list.c | 141 |
1 files changed, 141 insertions, 0 deletions
diff --git a/gcc/testsuite/jit.dg/test-linked-list.c b/gcc/testsuite/jit.dg/test-linked-list.c new file mode 100644 index 00000000000..28871d9f00a --- /dev/null +++ b/gcc/testsuite/jit.dg/test-linked-list.c @@ -0,0 +1,141 @@ +#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); +} |