5 #include "libgccjit++.h"
19 /* As per test-quadratic.c, let's try to inject the equivalent of:
21 extern double sqrt (double);
24 calc_discriminant (struct quadratic *q)
27 q->discriminant = (q->b * q->b) - (4 * q->a * q->c);
31 test_quadratic (double a, double b, double c, double *r1, double *r2)
37 calc_discriminant (&q);
38 if (q.discriminant > 0)
40 double s = sqrt (q.discriminant);
41 *r1 = (-b + s) / (2 * a);
42 *r2 = (-b - s) / (2 * a);
45 else if (q.discriminant == 0)
53 However, we'll use the C++ bindings.
56 /****************************************************************************
58 ****************************************************************************/
64 /* "double" and "(double *)". */
65 gccjit::type numeric_type
;
66 gccjit::type numeric_type_ptr
;
68 /* The value (double)0. */
71 gccjit::type int_type
;
72 gccjit::type void_type
;
74 /* "struct quadratic" */
75 gccjit::type quadratic
;
79 gccjit::field discriminant
;
81 /* "(struct quadratic *)" */
82 gccjit::type quadratic_ptr
;
84 gccjit::function calc_discriminant
;
86 gccjit::function sqrt
;
91 make_types (quadratic_test
&testcase
)
93 testcase
.numeric_type
= testcase
.ctxt
.get_type (GCC_JIT_TYPE_DOUBLE
);
94 testcase
.numeric_type_ptr
= testcase
.numeric_type
.get_pointer ();
95 testcase
.zero
= testcase
.ctxt
.zero (testcase
.numeric_type
);
97 testcase
.int_type
= testcase
.ctxt
.get_int_type
<int> ();
98 testcase
.void_type
= testcase
.ctxt
.get_type (GCC_JIT_TYPE_VOID
);
100 testcase
.a
= testcase
.ctxt
.new_field (testcase
.numeric_type
, "a");
101 testcase
.b
= testcase
.ctxt
.new_field (testcase
.numeric_type
, "b");
102 testcase
.c
= testcase
.ctxt
.new_field (testcase
.numeric_type
, "c");
103 testcase
.discriminant
=
104 testcase
.ctxt
.new_field (testcase
.numeric_type
, "discriminant");
105 CHECK_STRING_VALUE (testcase
.discriminant
.get_debug_string ().c_str (),
107 std::vector
<gccjit::field
> fields (4);
108 fields
[0] = testcase
.a
;
109 fields
[1] = testcase
.b
;
110 fields
[2] = testcase
.c
;
111 fields
[3] = testcase
.discriminant
;
113 testcase
.ctxt
.new_struct_type (
116 testcase
.quadratic_ptr
= testcase
.quadratic
.get_pointer ();
120 make_sqrt (quadratic_test
&testcase
)
122 std::vector
<gccjit::param
> params (1);
124 testcase
.ctxt
.new_param (testcase
.numeric_type
, "x");
126 testcase
.ctxt
.new_function (GCC_JIT_FUNCTION_IMPORTED
,
127 testcase
.numeric_type
,
134 make_calc_discriminant (quadratic_test
&testcase
)
136 /* Build "calc_discriminant". */
137 gccjit::param param_q
=
138 testcase
.ctxt
.new_param (testcase
.quadratic_ptr
, "q");
139 std::vector
<gccjit::param
> params (1);
141 testcase
.calc_discriminant
=
142 testcase
.ctxt
.new_function (GCC_JIT_FUNCTION_EXPORTED
,
147 gccjit::block block
= testcase
.calc_discriminant
.new_block ();
148 block
.add_comment ("(b^2 - 4ac)");
150 gccjit::rvalue q_a
= param_q
.dereference_field (testcase
.a
);
151 gccjit::rvalue q_b
= param_q
.dereference_field (testcase
.b
);
152 gccjit::rvalue q_c
= param_q
.dereference_field (testcase
.c
);
154 block
.add_assignment (
155 /* q->discriminant =... */
156 param_q
.dereference_field (testcase
.discriminant
),
157 /* (q->b * q->b) - (4 * q->a * q->c) */
158 testcase
.ctxt
.new_minus (
159 testcase
.numeric_type
,
162 testcase
.ctxt
.new_mult (
163 testcase
.numeric_type
,
166 /* (4 * (q->a * q->c)) */
167 testcase
.ctxt
.new_mult (
168 testcase
.numeric_type
,
170 testcase
.ctxt
.new_rvalue (
171 testcase
.numeric_type
,
174 testcase
.ctxt
.new_mult (
175 testcase
.numeric_type
,
176 q_a
, q_c
)))); /* end of add_assignment call. */
177 block
.end_with_return ();
181 make_test_quadratic (quadratic_test
&testcase
)
183 gccjit::param a
= testcase
.ctxt
.new_param (testcase
.numeric_type
, "a");
184 gccjit::param b
= testcase
.ctxt
.new_param (testcase
.numeric_type
, "b");
185 gccjit::param c
= testcase
.ctxt
.new_param (testcase
.numeric_type
, "c");
187 testcase
.ctxt
.new_param (testcase
.numeric_type_ptr
, "r1");
189 testcase
.ctxt
.new_param (testcase
.numeric_type_ptr
, "r2");
191 std::vector
<gccjit::param
> params (5);
198 gccjit::function test_quadratic
=
199 testcase
.ctxt
.new_function (GCC_JIT_FUNCTION_EXPORTED
,
205 /* struct quadratic q; */
206 gccjit::lvalue q
= test_quadratic
.new_local (testcase
.quadratic
, "q");
208 gccjit::block initial
= test_quadratic
.new_block ("initial");
209 gccjit::block on_positive_discriminant
210 = test_quadratic
.new_block ("positive_discriminant");
211 gccjit::block on_nonpositive_discriminant
212 = test_quadratic
.new_block ("nonpositive_discriminant");
213 gccjit::block on_zero_discriminant
214 = test_quadratic
.new_block ("zero_discriminant");
215 gccjit::block on_negative_discriminant
216 = test_quadratic
.new_block ("negative_discriminant");
218 CHECK_STRING_VALUE (on_zero_discriminant
.get_debug_string ().c_str (),
219 "zero_discriminant");
222 initial
.add_assignment (q
.access_field (testcase
.a
), a
);
224 initial
.add_assignment (q
.access_field (testcase
.b
), b
);
226 initial
.add_assignment (q
.access_field (testcase
.c
), c
);
227 /* calc_discriminant (&q); */
228 gccjit::rvalue address_of_q
= q
.get_address ();
229 initial
.add_call (testcase
.calc_discriminant
, address_of_q
);
231 initial
.add_comment ("if (q.discriminant > 0)");
232 initial
.end_with_conditional (
233 testcase
.ctxt
.new_gt (
234 q
.access_field (testcase
.discriminant
),
236 on_positive_discriminant
,
237 on_nonpositive_discriminant
);
239 /* Block: "on_positive_discriminant" */
240 /* double s = sqrt (q.discriminant); */
241 gccjit::lvalue s
= test_quadratic
.new_local (testcase
.numeric_type
, "s");
242 gccjit::rvalue discriminant_of_q
= q
.access_field (testcase
.discriminant
);
243 on_positive_discriminant
.add_assignment (
245 testcase
.ctxt
.new_call (testcase
.sqrt
, discriminant_of_q
));
247 gccjit::rvalue minus_b
=
248 testcase
.ctxt
.new_minus (
249 testcase
.numeric_type
,
251 gccjit::rvalue two_a
=
252 testcase
.ctxt
.new_mult (
253 testcase
.numeric_type
,
254 testcase
.ctxt
.new_rvalue (testcase
.numeric_type
, 2),
256 CHECK_STRING_VALUE (two_a
.get_debug_string ().c_str (),
259 on_positive_discriminant
.add_comment ("*r1 = (-b + s) / (2 * a);");
260 on_positive_discriminant
.add_assignment (
264 /* (-b + s) / (2 * a) */
265 testcase
.ctxt
.new_divide (
266 testcase
.numeric_type
,
267 testcase
.ctxt
.new_plus (
268 testcase
.numeric_type
,
273 on_positive_discriminant
.add_comment ("*r2 = (-b - s) / (2 * a)");
274 on_positive_discriminant
.add_assignment (
278 /* (-b - s) / (2 * a) */
279 testcase
.ctxt
.new_divide (
280 testcase
.numeric_type
,
281 testcase
.ctxt
.new_minus (
282 testcase
.numeric_type
,
288 on_positive_discriminant
.end_with_return (
289 testcase
.ctxt
.new_rvalue (testcase
.int_type
, 2));
291 /* Block: "on_nonpositive_discriminant" */
292 on_nonpositive_discriminant
.add_comment ("else if (q.discriminant == 0)");
293 on_nonpositive_discriminant
.end_with_conditional (
294 testcase
.ctxt
.new_eq (
295 q
.access_field (testcase
.discriminant
),
297 on_zero_discriminant
,
298 on_negative_discriminant
);
300 /* Block: "on_zero_discriminant" */
301 /* if (q.discriminant == 0) */
302 on_zero_discriminant
.add_comment ("*r1 = -b / (2 * a);");
303 on_zero_discriminant
.add_assignment (
308 testcase
.ctxt
.new_divide (
309 testcase
.numeric_type
,
314 on_zero_discriminant
.end_with_return (
315 testcase
.ctxt
.one (testcase
.int_type
));
317 /* Block: "on_negative_discriminant" */
319 on_negative_discriminant
.end_with_return (
320 testcase
.ctxt
.zero (testcase
.int_type
));
322 /* Verify that output stream operator << works. */
323 std::ostringstream os
;
324 os
<< "streamed output: " << address_of_q
;
325 CHECK_STRING_VALUE (os
.str ().c_str (), "streamed output: &q");
329 create_code (gcc_jit_context
*ctxt
, void *user_data
)
331 struct quadratic_test testcase
= {};
332 testcase
.ctxt
= ctxt
;
333 make_types (testcase
);
334 make_sqrt (testcase
);
335 make_calc_discriminant (testcase
);
336 make_test_quadratic (testcase
);
340 verify_code (gcc_jit_context
*ctxt
, gcc_jit_result
*result
)
342 typedef int (*fn_type
) (double a
, double b
, double c
,
343 double *r1
, double *r2
);
345 CHECK_NON_NULL (result
);
347 fn_type test_quadratic
=
348 (fn_type
)gcc_jit_result_get_code (result
, "test_quadratic");
349 CHECK_NON_NULL (test_quadratic
);
351 /* Verify that the code correctly solves quadratic equations. */
354 /* This one has two solutions: */
355 CHECK_VALUE (test_quadratic (1, 3, -4, &r1
, &r2
), 2);
357 CHECK_VALUE (r2
, -4);
359 /* This one has one solution: */
360 CHECK_VALUE (test_quadratic (4, 4, 1, &r1
, &r2
), 1);
361 CHECK_VALUE (r1
, -0.5);
363 /* This one has no real solutions: */
364 CHECK_VALUE (test_quadratic (4, 1, 1, &r1
, &r2
), 0);