16 /* Let's try to inject the equivalent of:
18 extern double sqrt (double);
21 calc_discriminant (struct quadratic *q)
24 q->discriminant = (q->b * q->b) - (4 * q->a * q->c);
28 test_quadratic (double a, double b, double c, double *r1, double *r2)
34 calc_discriminant (&q);
35 if (q.discriminant > 0)
37 double s = sqrt (q.discriminant);
38 *r1 = (-b + s) / (2 * a);
39 *r2 = (-b - s) / (2 * a);
42 else if (q.discriminant == 0)
53 gcc_jit_context
*ctxt
;
55 /* "double" and "(double *)". */
56 gcc_jit_type
*numeric_type
;
57 gcc_jit_type
*numeric_type_ptr
;
59 /* The value (double)0. */
62 gcc_jit_type
*int_type
;
63 gcc_jit_type
*void_type
;
65 /* "struct quadratic" */
66 gcc_jit_type
*quadratic
;
70 gcc_jit_field
*discriminant
;
72 /* "(struct quadratic *)" */
73 gcc_jit_type
*quadratic_ptr
;
75 gcc_jit_function
*calc_discriminant
;
77 gcc_jit_function
*sqrt
;
82 make_types (struct quadratic_test
*testcase
)
84 testcase
->numeric_type
=
85 gcc_jit_context_get_type (testcase
->ctxt
, GCC_JIT_TYPE_DOUBLE
);
86 testcase
->numeric_type_ptr
=
87 gcc_jit_type_get_pointer (testcase
->numeric_type
);
89 gcc_jit_context_zero (testcase
->ctxt
, testcase
->numeric_type
);
92 gcc_jit_context_get_type (testcase
->ctxt
, GCC_JIT_TYPE_INT
);
95 gcc_jit_context_get_type (testcase
->ctxt
, GCC_JIT_TYPE_VOID
);
98 gcc_jit_context_new_field (testcase
->ctxt
,
100 testcase
->numeric_type
,
103 gcc_jit_context_new_field (testcase
->ctxt
,
105 testcase
->numeric_type
,
108 gcc_jit_context_new_field (testcase
->ctxt
,
110 testcase
->numeric_type
,
112 testcase
->discriminant
=
113 gcc_jit_context_new_field (testcase
->ctxt
,
115 testcase
->numeric_type
,
117 gcc_jit_field
*fields
[] = {testcase
->a
,
120 testcase
->discriminant
};
121 testcase
->quadratic
=
122 gcc_jit_struct_as_type (
123 gcc_jit_context_new_struct_type (testcase
->ctxt
, NULL
,
124 "quadratic", 4, fields
));
125 testcase
->quadratic_ptr
= gcc_jit_type_get_pointer (testcase
->quadratic
);
129 make_sqrt (struct quadratic_test
*testcase
)
131 gcc_jit_param
*param_x
=
132 gcc_jit_context_new_param (testcase
->ctxt
, NULL
,
133 testcase
->numeric_type
, "x");
135 gcc_jit_context_new_function (testcase
->ctxt
, NULL
,
136 GCC_JIT_FUNCTION_IMPORTED
,
137 testcase
->numeric_type
,
144 make_calc_discriminant (struct quadratic_test
*testcase
)
146 /* Build "calc_discriminant". */
147 gcc_jit_param
*param_q
=
148 gcc_jit_context_new_param (testcase
->ctxt
, NULL
,
149 testcase
->quadratic_ptr
, "q");
150 testcase
->calc_discriminant
=
151 gcc_jit_context_new_function (testcase
->ctxt
, NULL
,
152 GCC_JIT_FUNCTION_INTERNAL
,
158 gcc_jit_function_new_block (testcase
->calc_discriminant
, NULL
);
159 gcc_jit_block_add_comment (
163 gcc_jit_rvalue
*q_a
=
164 gcc_jit_lvalue_as_rvalue (
165 gcc_jit_rvalue_dereference_field (
166 gcc_jit_param_as_rvalue (param_q
),
168 gcc_jit_rvalue
*q_b
=
169 gcc_jit_lvalue_as_rvalue (
170 gcc_jit_rvalue_dereference_field (
171 gcc_jit_param_as_rvalue (param_q
),
173 gcc_jit_rvalue
*q_c
=
174 gcc_jit_lvalue_as_rvalue (
175 gcc_jit_rvalue_dereference_field (
176 gcc_jit_param_as_rvalue (param_q
),
179 /* (q->b * q->b) - (4 * q->a * q->c) */
180 gcc_jit_rvalue
*rhs
=
181 gcc_jit_context_new_binary_op (
182 testcase
->ctxt
, NULL
,
183 GCC_JIT_BINARY_OP_MINUS
,
184 testcase
->numeric_type
,
187 gcc_jit_context_new_binary_op (
188 testcase
->ctxt
, NULL
,
189 GCC_JIT_BINARY_OP_MULT
,
190 testcase
->numeric_type
,
193 /* (4 * (q->a * q->c)) */
194 gcc_jit_context_new_binary_op (
195 testcase
->ctxt
, NULL
,
196 GCC_JIT_BINARY_OP_MULT
,
197 testcase
->numeric_type
,
199 gcc_jit_context_new_rvalue_from_int (
201 testcase
->numeric_type
,
204 gcc_jit_context_new_binary_op (
205 testcase
->ctxt
, NULL
,
206 GCC_JIT_BINARY_OP_MULT
,
207 testcase
->numeric_type
,
211 gcc_jit_object_get_debug_string (gcc_jit_rvalue_as_object (rhs
)),
212 "q->b * q->b - (double)4 * q->a * q->c");
214 gcc_jit_block_add_assignment (
217 /* q->discriminant =... */
218 gcc_jit_rvalue_dereference_field (
219 gcc_jit_param_as_rvalue (param_q
),
221 testcase
->discriminant
),
224 gcc_jit_block_end_with_void_return (blk
, NULL
);
228 make_test_quadratic (struct quadratic_test
*testcase
)
231 gcc_jit_context_new_param (testcase
->ctxt
, NULL
,
232 testcase
->numeric_type
, "a");
234 gcc_jit_context_new_param (testcase
->ctxt
, NULL
,
235 testcase
->numeric_type
, "b");
237 gcc_jit_context_new_param (testcase
->ctxt
, NULL
,
238 testcase
->numeric_type
, "c");
240 gcc_jit_context_new_param (testcase
->ctxt
, NULL
,
241 testcase
->numeric_type_ptr
, "r1");
243 gcc_jit_context_new_param (testcase
->ctxt
, NULL
,
244 testcase
->numeric_type_ptr
, "r2");
245 gcc_jit_param
*params
[] = {a
, b
, c
, r1
, r2
};
246 gcc_jit_function
*test_quadratic
=
247 gcc_jit_context_new_function (testcase
->ctxt
, NULL
,
248 GCC_JIT_FUNCTION_EXPORTED
,
253 /* struct quadratic q; */
255 gcc_jit_function_new_local (
256 test_quadratic
, NULL
,
260 gcc_jit_block
*initial
=
261 gcc_jit_function_new_block (test_quadratic
,
263 gcc_jit_block
*on_positive_discriminant
264 = gcc_jit_function_new_block (test_quadratic
,
265 "positive_discriminant");
267 gcc_jit_block
*on_nonpositive_discriminant
268 = gcc_jit_function_new_block (test_quadratic
,
269 "nonpositive_discriminant");
271 gcc_jit_block
*on_zero_discriminant
272 = gcc_jit_function_new_block (test_quadratic
,
273 "zero_discriminant");
275 gcc_jit_block
*on_negative_discriminant
276 = gcc_jit_function_new_block (test_quadratic
,
277 "negative_discriminant");
281 gcc_jit_block_add_assignment (
283 gcc_jit_lvalue_access_field (q
, NULL
, testcase
->a
),
284 gcc_jit_param_as_rvalue (a
));
286 gcc_jit_block_add_assignment (
288 gcc_jit_lvalue_access_field (q
, NULL
, testcase
->b
),
289 gcc_jit_param_as_rvalue (b
));
291 gcc_jit_block_add_assignment (
293 gcc_jit_lvalue_access_field (q
, NULL
, testcase
->c
),
294 gcc_jit_param_as_rvalue (c
));
295 /* calc_discriminant (&q); */
296 gcc_jit_rvalue
*address_of_q
= gcc_jit_lvalue_get_address (q
, NULL
);
297 gcc_jit_block_add_eval (
299 gcc_jit_context_new_call (
300 testcase
->ctxt
, NULL
,
301 testcase
->calc_discriminant
,
304 gcc_jit_block_add_comment (
306 "if (q.discriminant > 0)");
307 gcc_jit_block_end_with_conditional (
309 gcc_jit_context_new_comparison (
310 testcase
->ctxt
, NULL
,
311 GCC_JIT_COMPARISON_GT
,
312 gcc_jit_rvalue_access_field (
313 gcc_jit_lvalue_as_rvalue (q
),
315 testcase
->discriminant
),
317 on_positive_discriminant
,
318 on_nonpositive_discriminant
);
320 /* Block: "on_positive_discriminant" */
321 /* double s = sqrt (q.discriminant); */
322 gcc_jit_lvalue
*s
= gcc_jit_function_new_local (
323 test_quadratic
, NULL
,
324 testcase
->numeric_type
,
326 gcc_jit_rvalue
*discriminant_of_q
=
327 gcc_jit_rvalue_access_field (gcc_jit_lvalue_as_rvalue (q
),
329 testcase
->discriminant
);
330 gcc_jit_block_add_assignment (
331 on_positive_discriminant
, NULL
,
333 gcc_jit_context_new_call (
334 testcase
->ctxt
, NULL
,
336 1, &discriminant_of_q
));
338 gcc_jit_rvalue
*minus_b
=
339 gcc_jit_context_new_unary_op (
340 testcase
->ctxt
, NULL
,
341 GCC_JIT_UNARY_OP_MINUS
,
342 testcase
->numeric_type
,
343 gcc_jit_param_as_rvalue (b
));
344 gcc_jit_rvalue
*two_a
=
345 gcc_jit_context_new_binary_op (
346 testcase
->ctxt
, NULL
,
347 GCC_JIT_BINARY_OP_MULT
,
348 testcase
->numeric_type
,
349 gcc_jit_context_new_rvalue_from_int (
351 testcase
->numeric_type
,
353 gcc_jit_param_as_rvalue (a
));
355 gcc_jit_block_add_comment (
356 on_positive_discriminant
, NULL
,
357 "*r1 = (-b + s) / (2 * a);");
358 gcc_jit_block_add_assignment (
359 on_positive_discriminant
, NULL
,
362 gcc_jit_rvalue_dereference (
363 gcc_jit_param_as_rvalue (r1
), NULL
),
365 /* (-b + s) / (2 * a) */
366 gcc_jit_context_new_binary_op (
367 testcase
->ctxt
, NULL
,
368 GCC_JIT_BINARY_OP_DIVIDE
,
369 testcase
->numeric_type
,
370 gcc_jit_context_new_binary_op (
371 testcase
->ctxt
, NULL
,
372 GCC_JIT_BINARY_OP_PLUS
,
373 testcase
->numeric_type
,
375 gcc_jit_lvalue_as_rvalue (s
)),
378 gcc_jit_block_add_comment (
379 on_positive_discriminant
, NULL
,
380 "*r2 = (-b - s) / (2 * a)");
381 gcc_jit_block_add_assignment (
382 on_positive_discriminant
, NULL
,
385 gcc_jit_rvalue_dereference (
386 gcc_jit_param_as_rvalue (r2
), NULL
),
388 /* (-b - s) / (2 * a) */
389 gcc_jit_context_new_binary_op (
390 testcase
->ctxt
, NULL
,
391 GCC_JIT_BINARY_OP_DIVIDE
,
392 testcase
->numeric_type
,
393 gcc_jit_context_new_binary_op (
394 testcase
->ctxt
, NULL
,
395 GCC_JIT_BINARY_OP_MINUS
,
396 testcase
->numeric_type
,
398 gcc_jit_lvalue_as_rvalue (s
)),
402 gcc_jit_block_end_with_return (
403 on_positive_discriminant
, NULL
,
404 gcc_jit_context_new_rvalue_from_int (
409 /* Block: "on_nonpositive_discriminant" */
410 gcc_jit_block_add_comment (
411 on_nonpositive_discriminant
, NULL
,
412 "else if (q.discriminant == 0)");
413 gcc_jit_block_end_with_conditional (
414 on_nonpositive_discriminant
, NULL
,
415 gcc_jit_context_new_comparison (
416 testcase
->ctxt
, NULL
,
417 GCC_JIT_COMPARISON_EQ
,
418 gcc_jit_rvalue_access_field (
419 gcc_jit_lvalue_as_rvalue (q
),
421 testcase
->discriminant
),
423 on_zero_discriminant
,
424 on_negative_discriminant
);
426 /* Block: "on_zero_discriminant" */
427 gcc_jit_block_add_comment (
428 on_zero_discriminant
, NULL
,
429 "*r1 = -b / (2 * a);");
430 gcc_jit_block_add_assignment (
431 on_zero_discriminant
, NULL
,
434 gcc_jit_rvalue_dereference (
435 gcc_jit_param_as_rvalue (r1
), NULL
),
438 gcc_jit_context_new_binary_op (
439 testcase
->ctxt
, NULL
,
440 GCC_JIT_BINARY_OP_DIVIDE
,
441 testcase
->numeric_type
,
444 gcc_jit_block_end_with_return (
446 on_zero_discriminant
, NULL
,
447 gcc_jit_context_one (testcase
->ctxt
, testcase
->int_type
));
449 /* Block: "on_negative_discriminant" */
450 gcc_jit_block_end_with_return (
451 /* "else return 0;" */
452 on_negative_discriminant
, NULL
,
453 gcc_jit_context_zero (testcase
->ctxt
, testcase
->int_type
));
457 create_code (gcc_jit_context
*ctxt
, void *user_data
)
459 struct quadratic_test testcase
;
460 memset (&testcase
, 0, sizeof (testcase
));
461 testcase
.ctxt
= ctxt
;
462 make_types (&testcase
);
463 make_sqrt (&testcase
);
464 make_calc_discriminant (&testcase
);
465 make_test_quadratic (&testcase
);
469 verify_code (gcc_jit_context
*ctxt
, gcc_jit_result
*result
)
471 typedef int (*fn_type
) (double a
, double b
, double c
,
472 double *r1
, double *r2
);
474 CHECK_NON_NULL (result
);
476 fn_type test_quadratic
=
477 (fn_type
)gcc_jit_result_get_code (result
, "test_quadratic");
478 CHECK_NON_NULL (test_quadratic
);
480 /* Verify that the code correctly solves quadratic equations. */
483 /* This one has two solutions: */
484 CHECK_VALUE (test_quadratic (1, 3, -4, &r1
, &r2
), 2);
486 CHECK_VALUE (r2
, -4);
488 /* This one has one solution: */
489 CHECK_VALUE (test_quadratic (4, 4, 1, &r1
, &r2
), 1);
490 CHECK_VALUE (r1
, -0.5);
492 /* This one has no real solutions: */
493 CHECK_VALUE (test_quadratic (4, 1, 1, &r1
, &r2
), 0);