1#include <stdlib.h>
2#include <stdio.h>
3#include <string.h>
4
5#include "libgccjit.h"
6
7#include "harness.h"
8
9void
10create_code (gcc_jit_context *ctxt, void *user_data)
11{
12  /* Let's try to inject the equivalent of:
13
14	double
15	my_dot_product (int n, double *a, double *b)
16	{
17	  double result = 0.;
18	  for (int i = 0; i < n; i++)
19	    result += a[i] * b[i];
20	  return result
21	}
22
23     and see what the optimizer can do.  */
24  gcc_jit_type *val_type =
25    gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_DOUBLE);
26  gcc_jit_type *ptr_type = gcc_jit_type_get_pointer (val_type);
27  gcc_jit_type *int_type =
28    gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_INT);
29
30  gcc_jit_type *return_type = val_type;
31  gcc_jit_param *param_n =
32    gcc_jit_context_new_param (ctxt, NULL, int_type, "n");
33  gcc_jit_param *param_a =
34    gcc_jit_context_new_param (ctxt, NULL, ptr_type, "a");
35  gcc_jit_param *param_b =
36    gcc_jit_context_new_param (ctxt, NULL, ptr_type, "b");
37  gcc_jit_param *params[3] = {param_n, param_a, param_b};
38  gcc_jit_function *func =
39    gcc_jit_context_new_function (ctxt, NULL,
40				  GCC_JIT_FUNCTION_EXPORTED,
41				  return_type,
42				  "my_dot_product",
43				  3, params, 0);
44
45  gcc_jit_block *initial = gcc_jit_function_new_block (func, "initial");
46  gcc_jit_block *loop_test = gcc_jit_function_new_block (func, "loop_test");
47  gcc_jit_block *loop_body = gcc_jit_function_new_block (func, "loop_body");
48  gcc_jit_block *final = gcc_jit_function_new_block (func, "final");
49
50  /* Build: "double result = 0.;" */
51  gcc_jit_lvalue *result =
52    gcc_jit_function_new_local (func, NULL, val_type, "result");
53
54  gcc_jit_block_add_assignment (initial, NULL,
55    result, gcc_jit_context_zero (ctxt, val_type));
56
57  /* Build: "for (int i = 0; i < n; i++)" */
58  gcc_jit_lvalue *i =
59    gcc_jit_function_new_local (func, NULL, int_type, "i");
60  gcc_jit_block_add_assignment (initial, NULL,
61    i, gcc_jit_context_zero (ctxt, int_type));
62
63  gcc_jit_block_end_with_jump (initial, NULL, loop_test);
64
65  gcc_jit_block_end_with_conditional (
66    loop_test, NULL,
67
68    /* (i < n) */
69    gcc_jit_context_new_comparison (
70      ctxt, NULL,
71      GCC_JIT_COMPARISON_LT,
72      gcc_jit_lvalue_as_rvalue (i),
73      gcc_jit_param_as_rvalue (param_n)),
74
75    loop_body,
76    final);
77
78  /* Build: "result += a[i] * b[i];" */
79  gcc_jit_block_add_assignment_op (
80    loop_body, NULL,
81    result,
82    GCC_JIT_BINARY_OP_PLUS,
83    gcc_jit_context_new_binary_op (
84      ctxt, NULL,
85      GCC_JIT_BINARY_OP_MULT,
86      val_type,
87      gcc_jit_lvalue_as_rvalue (
88	gcc_jit_context_new_array_access (
89          ctxt, NULL,
90	  gcc_jit_param_as_rvalue (param_a),
91	  gcc_jit_lvalue_as_rvalue (i))),
92      gcc_jit_lvalue_as_rvalue (
93	gcc_jit_context_new_array_access (
94          ctxt, NULL,
95	  gcc_jit_param_as_rvalue (param_b),
96	  gcc_jit_lvalue_as_rvalue (i)))));
97
98  /* Build: "i++" */
99  gcc_jit_block_add_assignment_op (
100    loop_body, NULL,
101    i,
102    GCC_JIT_BINARY_OP_PLUS,
103    gcc_jit_context_one (ctxt, int_type));
104
105  gcc_jit_block_end_with_jump (loop_body, NULL, loop_test);
106
107  /* Build: "return result;" */
108  gcc_jit_block_end_with_return (
109    final,
110    NULL,
111    gcc_jit_lvalue_as_rvalue (result));
112}
113
114void
115verify_code (gcc_jit_context *ctxt, gcc_jit_result *result)
116{
117  typedef double (*my_dot_product_fn_type) (int n, double *a, double *b);
118  CHECK_NON_NULL (result);
119
120  my_dot_product_fn_type my_dot_product =
121    (my_dot_product_fn_type)gcc_jit_result_get_code (result,
122						     "my_dot_product");
123  CHECK_NON_NULL (my_dot_product);
124  double test_array[] = {1., 2., 3., 4., 5., 6., 7., 8., 9., 10.};
125  double val = my_dot_product (10, test_array, test_array);
126  note ("my_dot_product returned: %f", val);
127  CHECK_VALUE (val, 385.0);
128}
129
130