test-linked-list.c 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142
  1. #include <stdlib.h>
  2. #include <stdio.h>
  3. #include "libgccjit.h"
  4. #include "harness.h"
  5. /* A doubly-linked list, to ensure that the JIT API can cope with
  6. self-referential types. */
  7. struct node
  8. {
  9. struct node *prev;
  10. struct node *next;
  11. int value;
  12. };
  13. void
  14. create_code (gcc_jit_context *ctxt, void *user_data)
  15. {
  16. /* Let's try to inject the equivalent of:
  17. int
  18. test_linked_list (struct node *n)
  19. {
  20. int total = 0;
  21. while (n)
  22. {
  23. total += n->value;
  24. n = n->next;
  25. }
  26. return total;
  27. }
  28. */
  29. gcc_jit_type *t_int =
  30. gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_INT);
  31. gcc_jit_struct *t_node =
  32. gcc_jit_context_new_opaque_struct (ctxt, NULL, "node");
  33. gcc_jit_type *t_node_ptr =
  34. gcc_jit_type_get_pointer (gcc_jit_struct_as_type (t_node));
  35. gcc_jit_field *f_prev =
  36. gcc_jit_context_new_field (ctxt, NULL, t_node_ptr, "prev");
  37. gcc_jit_field *f_next =
  38. gcc_jit_context_new_field (ctxt, NULL, t_node_ptr, "next");
  39. gcc_jit_field *f_value =
  40. gcc_jit_context_new_field (ctxt, NULL, t_int, "value");
  41. gcc_jit_field *fields[] = {f_prev, f_next, f_value};
  42. gcc_jit_struct_set_fields (t_node, NULL, 3, fields);
  43. /* Build the test function. */
  44. gcc_jit_param *param_n =
  45. gcc_jit_context_new_param (ctxt, NULL, t_node_ptr, "n");
  46. gcc_jit_function *fn =
  47. gcc_jit_context_new_function (ctxt, NULL,
  48. GCC_JIT_FUNCTION_EXPORTED,
  49. t_int,
  50. "test_linked_list",
  51. 1, &param_n,
  52. 0);
  53. /* int total; */
  54. gcc_jit_lvalue *total =
  55. gcc_jit_function_new_local (fn, NULL, t_int, "total");
  56. gcc_jit_block *initial = gcc_jit_function_new_block (fn, "initial");
  57. gcc_jit_block *loop_test = gcc_jit_function_new_block (fn, "loop_test");
  58. gcc_jit_block *loop_body = gcc_jit_function_new_block (fn, "loop_body");
  59. gcc_jit_block *final = gcc_jit_function_new_block (fn, "final");
  60. /* total = 0; */
  61. gcc_jit_block_add_assignment (
  62. initial, NULL,
  63. total,
  64. gcc_jit_context_zero (ctxt, t_int));
  65. gcc_jit_block_end_with_jump (initial, NULL, loop_test);
  66. /* while (n) */
  67. gcc_jit_block_end_with_conditional (
  68. loop_test, NULL,
  69. gcc_jit_context_new_comparison (ctxt, NULL,
  70. GCC_JIT_COMPARISON_NE,
  71. gcc_jit_param_as_rvalue (param_n),
  72. gcc_jit_context_null (ctxt, t_node_ptr)),
  73. loop_body,
  74. final);
  75. /* total += n->value; */
  76. gcc_jit_block_add_assignment_op (
  77. loop_body, NULL,
  78. total,
  79. GCC_JIT_BINARY_OP_PLUS,
  80. gcc_jit_lvalue_as_rvalue (
  81. gcc_jit_rvalue_dereference_field (
  82. gcc_jit_param_as_rvalue (param_n),
  83. NULL,
  84. f_value)));
  85. /* n = n->next; */
  86. gcc_jit_block_add_assignment (
  87. loop_body, NULL,
  88. gcc_jit_param_as_lvalue (param_n),
  89. gcc_jit_lvalue_as_rvalue (
  90. gcc_jit_rvalue_dereference_field (
  91. gcc_jit_param_as_rvalue (param_n),
  92. NULL,
  93. f_next)));
  94. gcc_jit_block_end_with_jump (loop_body, NULL, loop_test);
  95. /* return total; */
  96. gcc_jit_block_end_with_return (
  97. final, NULL, gcc_jit_lvalue_as_rvalue (total));
  98. }
  99. void
  100. verify_code (gcc_jit_context *ctxt, gcc_jit_result *result)
  101. {
  102. struct node a, b, c;
  103. typedef int (*fn_type) (struct node *n);
  104. CHECK_NON_NULL (result);
  105. fn_type test_linked_list =
  106. (fn_type)gcc_jit_result_get_code (result, "test_linked_list");
  107. CHECK_NON_NULL (test_linked_list);
  108. /* Construct a simple linked-list on the stack: a->b->c: */
  109. a.prev = NULL;
  110. a.next = &b;
  111. a.value = 5;
  112. b.prev = &a;
  113. b.next = &c;
  114. b.value = 3;
  115. c.prev = &b;
  116. c.next = NULL;
  117. c.value = 7;
  118. CHECK_VALUE (test_linked_list (NULL), 0);
  119. CHECK_VALUE (test_linked_list (&a), 15);
  120. CHECK_VALUE (test_linked_list (&b), 10);
  121. CHECK_VALUE (test_linked_list (&c), 7);
  122. }