1 #include <stdlib.h>
2 #include <stdio.h>
3 #include <string.h>
4 
5 #include "libgccjit.h"
6 
7 #include "harness.h"
8 
9 void
create_code(gcc_jit_context * ctxt,void * user_data)10 create_code (gcc_jit_context *ctxt, void *user_data)
11 {
12   /* Let's try to inject the equivalent of:
13 
14 	double
15 	test_nested_loops (int n, double *a, double *b)
16 	{
17 	  double result = 0.;
18 	  for (int i = 0; i < n; i++)
19 	    for (int j = 0; j < n; j++)
20 	      result += a[i] * b[j];
21 	  return result
22 	}
23   */
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 				  "test_nested_loops",
43 				  3, params, 0);
44 
45   /* Create locals. */
46   gcc_jit_lvalue *result =
47     gcc_jit_function_new_local (func, NULL, val_type, "result");
48   gcc_jit_lvalue *i =
49     gcc_jit_function_new_local (func, NULL, int_type, "i");
50   gcc_jit_lvalue *j =
51     gcc_jit_function_new_local (func, NULL, int_type, "j");
52 
53   /* Create basic blocks. */
54   gcc_jit_block *b_entry =
55     gcc_jit_function_new_block (func, "b_entry");
56   gcc_jit_block *b_outer_loop_cond =
57     gcc_jit_function_new_block (func, "b_outer_loop_cond");
58   gcc_jit_block *b_outer_loop_head =
59     gcc_jit_function_new_block (func, "b_outer_loop_head");
60   gcc_jit_block *b_outer_loop_tail =
61     gcc_jit_function_new_block (func, "b_outer_loop_tail");
62   gcc_jit_block *b_inner_loop_cond =
63     gcc_jit_function_new_block (func, "b_inner_loop_cond");
64   gcc_jit_block *b_inner_loop_body =
65     gcc_jit_function_new_block (func, "b_inner_loop_body");
66   gcc_jit_block *b_exit =
67     gcc_jit_function_new_block (func, "b_exit");
68 
69 
70   /* Populate b_entry. */
71 
72   /* "result = 0.;" */
73   gcc_jit_block_add_assignment (
74     b_entry, NULL,
75     result,
76     gcc_jit_context_zero (ctxt, val_type));
77   /* "i = 0;" */
78   gcc_jit_block_add_assignment (
79     b_entry, NULL,
80     i,
81     gcc_jit_context_zero (ctxt, int_type));
82   gcc_jit_block_end_with_jump (b_entry, NULL, b_outer_loop_cond);
83 
84   /* Populate b_outer_loop_cond. */
85   gcc_jit_block_end_with_conditional (
86     b_outer_loop_cond,
87     NULL,
88     /* (i < n) */
89     gcc_jit_context_new_comparison (
90       ctxt, NULL,
91       GCC_JIT_COMPARISON_LT,
92       gcc_jit_lvalue_as_rvalue (i),
93       gcc_jit_param_as_rvalue (param_n)),
94     b_outer_loop_head,
95     b_exit);
96 
97   /* Populate b_outer_loop_head. */
98   /* j = 0; */
99   gcc_jit_block_add_assignment (
100     b_outer_loop_head, NULL,
101     j,
102     gcc_jit_context_zero (ctxt, int_type));
103   gcc_jit_block_end_with_jump (b_outer_loop_head, NULL, b_inner_loop_cond);
104 
105   /* Populate b_inner_loop_cond. */
106   gcc_jit_block_end_with_conditional (
107     b_inner_loop_cond,
108     NULL,
109     /* (j < n) */
110     gcc_jit_context_new_comparison (
111       ctxt, NULL,
112       GCC_JIT_COMPARISON_LT,
113       gcc_jit_lvalue_as_rvalue (j),
114       gcc_jit_param_as_rvalue (param_n)),
115     b_inner_loop_body,
116     b_outer_loop_tail);
117 
118   /* Populate b_inner_loop_body. */
119   /* "result += a[i] * b[j];" */
120   gcc_jit_block_add_assignment_op (
121     b_inner_loop_body, NULL,
122     result,
123     GCC_JIT_BINARY_OP_PLUS,
124     gcc_jit_context_new_binary_op (
125       ctxt, NULL,
126       GCC_JIT_BINARY_OP_MULT,
127       val_type,
128       gcc_jit_lvalue_as_rvalue (
129         gcc_jit_context_new_array_access(
130           ctxt, NULL,
131           gcc_jit_param_as_rvalue (param_a),
132           gcc_jit_lvalue_as_rvalue (i))),
133       gcc_jit_lvalue_as_rvalue (
134         gcc_jit_context_new_array_access(
135           ctxt, NULL,
136           gcc_jit_param_as_rvalue (param_b),
137           gcc_jit_lvalue_as_rvalue (j)))));
138   /* "j++" */
139   gcc_jit_block_add_assignment_op (
140     b_inner_loop_body, NULL,
141     j,
142     GCC_JIT_BINARY_OP_PLUS,
143     gcc_jit_context_one (ctxt, int_type));
144 
145   gcc_jit_block_end_with_jump (b_inner_loop_body, NULL, b_inner_loop_cond);
146 
147   /* Populate b_outer_loop_tail. */
148   /* "i++" */
149   gcc_jit_block_add_assignment_op (
150     b_outer_loop_tail, NULL,
151     i,
152     GCC_JIT_BINARY_OP_PLUS,
153     gcc_jit_context_one (ctxt, int_type));
154   gcc_jit_block_end_with_jump (b_outer_loop_tail, NULL, b_outer_loop_cond);
155 
156   /* Populate b_exit. */
157   /* "return result;" */
158   gcc_jit_block_end_with_return (
159     b_exit,
160     NULL,
161     gcc_jit_lvalue_as_rvalue (result));
162 }
163 
164 void
verify_code(gcc_jit_context * ctxt,gcc_jit_result * result)165 verify_code (gcc_jit_context *ctxt, gcc_jit_result *result)
166 {
167   typedef double (*test_nested_loops_fn_type) (int n, double *a, double *b);
168   CHECK_NON_NULL (result);
169 
170   test_nested_loops_fn_type test_nested_loops =
171     (test_nested_loops_fn_type)gcc_jit_result_get_code (result,
172 						     "test_nested_loops");
173   CHECK_NON_NULL (test_nested_loops);
174   double test_a[] = {1., 2., 3., 4., 5., 6., 7., 8., 9., 10.};
175   double test_b[] = {5., 6., 7., 8., 9., 10., 1., 2., 3., 4.};
176   double val = test_nested_loops (10, test_a, test_b);
177   note ("test_nested_loops returned: %f", val);
178   CHECK_VALUE (val, 3025.0);
179 }
180