This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[jit] Add operator overloading to the C++ API.
- From: David Malcolm <dmalcolm at redhat dot com>
- To: jit at gcc dot gnu dot org, gcc-patches at gcc dot gnu dot org
- Cc: David Malcolm <dmalcolm at redhat dot com>
- Date: Mon, 10 Feb 2014 14:17:52 -0500
- Subject: [jit] Add operator overloading to the C++ API.
- Authentication-results: sourceware.org; auth=none
Committed to branch dmalcolm/jit:
gcc/jit/
* libgccjit++.h (gccjit::object::get_context): New method.
(gccjit::function): Add overloaded operator () for various
numbers of arguments as a very terse way of creating function calls.
(gccjit::rvalue::get_type): New method.
(operator-): New overloaded unary op for rvalues.
(operator~): Likewise.
(operator!): Likewise.
(operator+): New overloaded binary op for rvalues.
(operator-): Likewise.
(operator*): Likewise.
(operator/): Likewise.
(operator%): Likewise.
(operator&): Likewise.
(operator^): Likewise.
(operator|): Likewise.
(operator&&): Likewise.
(operator||): Likewise.
(operator==): New overloaded comparison for rvalues.
(operator!=): Likewise.
(operator<): Likewise.
(operator<=): Likewise.
(operator>): Likewise.
(operator>=): Likewise.
(operator*): New overloaded operator for dereferencing an
rvalue representing a pointer.
* libgccjit.c (gcc_jit_rvalue_get_type): New.
* libgccjit.h (gcc_jit_rvalue_get_type): New.
* libgccjit.map (gcc_jit_rvalue_get_type): New.
gcc/testsuite/
* jit.dg/test-operator-overloading.cc: New testcase, a
rewrite of test-quadratic.cc to use operator overloading.
---
gcc/jit/ChangeLog.jit | 36 +++
gcc/jit/libgccjit++.h | 173 ++++++++++++
gcc/jit/libgccjit.c | 8 +
gcc/jit/libgccjit.h | 3 +
gcc/jit/libgccjit.map | 1 +
gcc/testsuite/ChangeLog.jit | 5 +
gcc/testsuite/jit.dg/test-operator-overloading.cc | 306 ++++++++++++++++++++++
7 files changed, 532 insertions(+)
create mode 100644 gcc/testsuite/jit.dg/test-operator-overloading.cc
diff --git a/gcc/jit/ChangeLog.jit b/gcc/jit/ChangeLog.jit
index bd209ed..9b44728 100644
--- a/gcc/jit/ChangeLog.jit
+++ b/gcc/jit/ChangeLog.jit
@@ -1,5 +1,41 @@
2014-02-10 David Malcolm <dmalcolm@redhat.com>
+ * libgccjit++.h (gccjit::object::get_context): New method.
+ (gccjit::function): Add overloaded operator () for various
+ numbers of arguments as a very terse way of creating function calls.
+ (gccjit::rvalue::get_type): New method.
+
+ (operator-): New overloaded unary op for rvalues.
+ (operator~): Likewise.
+ (operator!): Likewise.
+
+ (operator+): New overloaded binary op for rvalues.
+ (operator-): Likewise.
+ (operator*): Likewise.
+ (operator/): Likewise.
+ (operator%): Likewise.
+ (operator&): Likewise.
+ (operator^): Likewise.
+ (operator|): Likewise.
+ (operator&&): Likewise.
+ (operator||): Likewise.
+
+ (operator==): New overloaded comparison for rvalues.
+ (operator!=): Likewise.
+ (operator<): Likewise.
+ (operator<=): Likewise.
+ (operator>): Likewise.
+ (operator>=): Likewise.
+
+ (operator*): New overloaded operator for dereferencing an
+ rvalue representing a pointer.
+
+ * libgccjit.c (gcc_jit_rvalue_get_type): New.
+ * libgccjit.h (gcc_jit_rvalue_get_type): New.
+ * libgccjit.map (gcc_jit_rvalue_get_type): New.
+
+2014-02-10 David Malcolm <dmalcolm@redhat.com>
+
* libgccjit++.h (gccjit::context::new_minus): New method,
providing a way to do a specific unary op with less typing.
(gccjit::context::new_bitwise_negate): Likewise.
diff --git a/gcc/jit/libgccjit++.h b/gcc/jit/libgccjit++.h
index ff22d1e..fab1a74 100644
--- a/gcc/jit/libgccjit++.h
+++ b/gcc/jit/libgccjit++.h
@@ -27,6 +27,8 @@ namespace gccjit
class object
{
public:
+ context get_context () const;
+
std::string get_debug_string () const;
protected:
@@ -296,6 +298,16 @@ namespace gccjit
void add_return (rvalue rvalue,
location loc = location ());
+
+ /* A series of overloaded operator () with various numbers of arguments
+ for a very terse way of creating a call to this function. The call
+ is created within the same context as the function itself, which may
+ not be what you want. */
+ rvalue operator() (location loc = location ());
+ rvalue operator() (rvalue arg0,
+ location loc = location ());
+ rvalue operator() (rvalue arg0, rvalue arg1,
+ location loc = location ());
};
class label : public object
@@ -314,6 +326,8 @@ namespace gccjit
rvalue (gcc_jit_rvalue *inner);
gcc_jit_rvalue *get_inner_rvalue ();
+ type get_type ();
+
rvalue access_field (field field,
location loc = location ());
@@ -345,6 +359,42 @@ namespace gccjit
gcc_jit_param *get_inner_param ();
};
+
+
+ /* Overloaded operators, for those who want the most terse API
+ (at the possible risk of being a little too magical).
+
+ In each case, the first parameter is used to determine which context
+ owns the resulting expression, and, where appropriate, what the
+ latter's type is. */
+
+ /* Unary operators. */
+ rvalue operator- (rvalue a); // unary minus
+ rvalue operator~ (rvalue a); // unary bitwise negate
+ rvalue operator! (rvalue a); // unary logical negate
+
+ /* Binary operators. */
+ rvalue operator+ (rvalue a, rvalue b);
+ rvalue operator- (rvalue a, rvalue b);
+ rvalue operator* (rvalue a, rvalue b);
+ rvalue operator/ (rvalue a, rvalue b);
+ rvalue operator% (rvalue a, rvalue b);
+ rvalue operator& (rvalue a, rvalue b); // bitwise and
+ rvalue operator^ (rvalue a, rvalue b); // bitwise_xor
+ rvalue operator| (rvalue a, rvalue b); // bitwise_or
+ rvalue operator&& (rvalue a, rvalue b); // logical_and
+ rvalue operator|| (rvalue a, rvalue b); // logical_or
+
+ /* Comparisons. */
+ rvalue operator== (rvalue a, rvalue b);
+ rvalue operator!= (rvalue a, rvalue b);
+ rvalue operator< (rvalue a, rvalue b);
+ rvalue operator<= (rvalue a, rvalue b);
+ rvalue operator> (rvalue a, rvalue b);
+ rvalue operator>= (rvalue a, rvalue b);
+
+ /* Dereferencing. */
+ lvalue operator* (rvalue ptr);
}
/****************************************************************************
@@ -835,6 +885,12 @@ context::new_array_access (rvalue ptr,
}
// class object
+inline context
+object::get_context () const
+{
+ return context (gcc_jit_object_get_context (m_inner_obj));
+}
+
inline std::string
object::get_debug_string () const
{
@@ -1038,6 +1094,28 @@ function::add_return (rvalue rvalue,
rvalue.get_inner_rvalue ());
}
+inline rvalue
+function::operator() (location loc)
+{
+ return get_context ().new_call (*this, loc);
+}
+inline rvalue
+function::operator() (rvalue arg0,
+ location loc)
+{
+ return get_context ().new_call (*this,
+ arg0,
+ loc);
+}
+inline rvalue
+function::operator() (rvalue arg0, rvalue arg1,
+ location loc)
+{
+ return get_context ().new_call (*this,
+ arg0, arg1,
+ loc);
+}
+
// class label
inline label::label () : object (NULL) {}
inline label::label (gcc_jit_label *inner)
@@ -1064,6 +1142,12 @@ rvalue::get_inner_rvalue ()
return reinterpret_cast<gcc_jit_rvalue *> (get_inner_object ());
}
+inline type
+rvalue::get_type ()
+{
+ return type (gcc_jit_rvalue_get_type (get_inner_rvalue ()));
+}
+
inline rvalue
rvalue::access_field (field field,
location loc)
@@ -1123,6 +1207,95 @@ inline param::param (gcc_jit_param *inner)
: lvalue (gcc_jit_param_as_lvalue (inner))
{}
+/* Overloaded operators. */
+// Unary operators
+inline rvalue operator- (rvalue a)
+{
+ return a.get_context ().new_minus (a.get_type (), a);
+}
+inline rvalue operator~ (rvalue a)
+{
+ return a.get_context ().new_bitwise_negate (a.get_type (), a);
+}
+inline rvalue operator! (rvalue a)
+{
+ return a.get_context ().new_logical_negate (a.get_type (), a);
+}
+
+// Binary operators
+inline rvalue operator+ (rvalue a, rvalue b)
+{
+ return a.get_context ().new_plus (a.get_type (), a, b);
+}
+inline rvalue operator- (rvalue a, rvalue b)
+{
+ return a.get_context ().new_minus (a.get_type (), a, b);
+}
+inline rvalue operator* (rvalue a, rvalue b)
+{
+ return a.get_context ().new_mult (a.get_type (), a, b);
+}
+inline rvalue operator/ (rvalue a, rvalue b)
+{
+ return a.get_context ().new_divide (a.get_type (), a, b);
+}
+inline rvalue operator% (rvalue a, rvalue b)
+{
+ return a.get_context ().new_modulo (a.get_type (), a, b);
+}
+inline rvalue operator& (rvalue a, rvalue b)
+{
+ return a.get_context ().new_bitwise_and (a.get_type (), a, b);
+}
+inline rvalue operator^ (rvalue a, rvalue b)
+{
+ return a.get_context ().new_bitwise_xor (a.get_type (), a, b);
+}
+inline rvalue operator| (rvalue a, rvalue b)
+{
+ return a.get_context ().new_bitwise_or (a.get_type (), a, b);
+}
+inline rvalue operator&& (rvalue a, rvalue b)
+{
+ return a.get_context ().new_logical_and (a.get_type (), a, b);
+}
+inline rvalue operator|| (rvalue a, rvalue b)
+{
+ return a.get_context ().new_logical_or (a.get_type (), a, b);
+}
+
+/* Comparisons. */
+inline rvalue operator== (rvalue a, rvalue b)
+{
+ return a.get_context ().new_eq (a, b);
+}
+inline rvalue operator!= (rvalue a, rvalue b)
+{
+ return a.get_context ().new_ne (a, b);
+}
+inline rvalue operator< (rvalue a, rvalue b)
+{
+ return a.get_context ().new_lt (a, b);
+}
+inline rvalue operator<= (rvalue a, rvalue b)
+{
+ return a.get_context ().new_le (a, b);
+}
+inline rvalue operator> (rvalue a, rvalue b)
+{
+ return a.get_context ().new_gt (a, b);
+}
+inline rvalue operator>= (rvalue a, rvalue b)
+{
+ return a.get_context ().new_ge (a, b);
+}
+
+/* Dereferencing. */
+inline lvalue operator* (rvalue ptr)
+{
+ return ptr.dereference ();
+}
+
} // namespace gccjit
#endif /* #ifndef LIBGCCJIT_PLUS_PLUS_H */
diff --git a/gcc/jit/libgccjit.c b/gcc/jit/libgccjit.c
index 181954d..3f39984 100644
--- a/gcc/jit/libgccjit.c
+++ b/gcc/jit/libgccjit.c
@@ -452,6 +452,14 @@ gcc_jit_rvalue_as_object (gcc_jit_rvalue *rvalue)
return static_cast <gcc_jit_object *> (rvalue->as_object ());
}
+gcc_jit_type *
+gcc_jit_rvalue_get_type (gcc_jit_rvalue *rvalue)
+{
+ RETURN_NULL_IF_FAIL (rvalue, NULL, "NULL rvalue");
+
+ return static_cast <gcc_jit_type *> (rvalue->get_type ());
+}
+
gcc_jit_rvalue *
gcc_jit_context_new_rvalue_from_int (gcc_jit_context *ctxt,
gcc_jit_type *numeric_type,
diff --git a/gcc/jit/libgccjit.h b/gcc/jit/libgccjit.h
index 1ef55d0..e0161ba 100644
--- a/gcc/jit/libgccjit.h
+++ b/gcc/jit/libgccjit.h
@@ -467,6 +467,9 @@ gcc_jit_lvalue_as_rvalue (gcc_jit_lvalue *lvalue);
extern gcc_jit_object *
gcc_jit_rvalue_as_object (gcc_jit_rvalue *rvalue);
+extern gcc_jit_type *
+gcc_jit_rvalue_get_type (gcc_jit_rvalue *rvalue);
+
/* Integer constants. */
extern gcc_jit_rvalue *
gcc_jit_context_new_rvalue_from_int (gcc_jit_context *ctxt,
diff --git a/gcc/jit/libgccjit.map b/gcc/jit/libgccjit.map
index cbf9b33..6dc700d 100644
--- a/gcc/jit/libgccjit.map
+++ b/gcc/jit/libgccjit.map
@@ -63,6 +63,7 @@
gcc_jit_rvalue_as_object;
gcc_jit_rvalue_dereference;
gcc_jit_rvalue_dereference_field;
+ gcc_jit_rvalue_get_type;
gcc_jit_type_as_object;
gcc_jit_type_get_const;
gcc_jit_type_get_pointer;
diff --git a/gcc/testsuite/ChangeLog.jit b/gcc/testsuite/ChangeLog.jit
index ee2dc40..11987e0 100644
--- a/gcc/testsuite/ChangeLog.jit
+++ b/gcc/testsuite/ChangeLog.jit
@@ -1,5 +1,10 @@
2014-02-10 David Malcolm <dmalcolm@redhat.com>
+ * jit.dg/test-operator-overloading.cc: New testcase, a
+ rewrite of test-quadratic.cc to use operator overloading.
+
+2014-02-10 David Malcolm <dmalcolm@redhat.com>
+
* jit.dg/test-quadratic.cc (make_calc_discriminant): Make use of
new methods of the C++ wrapper API to shorten the example code.
(make_test_quadratic): Likewise.
diff --git a/gcc/testsuite/jit.dg/test-operator-overloading.cc b/gcc/testsuite/jit.dg/test-operator-overloading.cc
new file mode 100644
index 0000000..313b3e6
--- /dev/null
+++ b/gcc/testsuite/jit.dg/test-operator-overloading.cc
@@ -0,0 +1,306 @@
+/* Test of C++ API. */
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "libgccjit++.h"
+
+#include <sstream>
+
+#include "harness.h"
+
+struct quadratic
+{
+ double a;
+ double b;
+ double c;
+ double discriminant;
+};
+
+/* As per test-quadratic.cc, let's try to inject the equivalent of:
+
+ extern double sqrt (double);
+
+ void
+ calc_discriminant (struct quadratic *q)
+ {
+ // (b^2 - 4ac)
+ q->discriminant = (q->b * q->b) - (4 * q->a * q->c);
+ }
+
+ int
+ test_quadratic (double a, double b, double c, double *r1, double *r2)
+ {
+ struct quadratic q;
+ q.a = a;
+ q.b = b;
+ q.c = c;
+ calc_discriminant (&q);
+ if (q.discriminant > 0)
+ {
+ double s = sqrt (q.discriminant);
+ *r1 = (-b + s) / (2 * a);
+ *r2 = (-b - s) / (2 * a);
+ return 2;
+ }
+ else if (q.discriminant == 0)
+ {
+ *r1 = -b / (2 * a);
+ return 1;
+ }
+ else return 0;
+ }
+
+ However, we'll use operator overloading for maxium brevity, at the
+ risk of perhaps being too "magical".
+*/
+
+/****************************************************************************
+ Test case
+ ****************************************************************************/
+
+struct quadratic_test
+{
+ gccjit::context ctxt;
+
+ /* "double" and "(double *)". */
+ gccjit::type numeric_type;
+ gccjit::type numeric_type_ptr;
+
+ /* The value (double)0. */
+ gccjit::rvalue zero;
+
+ gccjit::type int_type;
+
+ /* "struct quadratic" */
+ gccjit::type quadratic;
+ gccjit::field a;
+ gccjit::field b;
+ gccjit::field c;
+ gccjit::field discriminant;
+
+ /* "(struct quadratic *)" */
+ gccjit::type quadratic_ptr;
+
+ gccjit::function calc_discriminant;
+
+ gccjit::function sqrt;
+
+};
+
+static void
+make_types (quadratic_test &testcase)
+{
+ testcase.numeric_type = testcase.ctxt.get_type (GCC_JIT_TYPE_DOUBLE);
+ testcase.numeric_type_ptr = testcase.numeric_type.get_pointer ();
+ testcase.zero = testcase.ctxt.zero (testcase.numeric_type);
+
+ testcase.int_type = testcase.ctxt.get_type (GCC_JIT_TYPE_INT);
+
+ testcase.a = testcase.ctxt.new_field (testcase.numeric_type, "a");
+ testcase.b = testcase.ctxt.new_field (testcase.numeric_type, "b");
+ testcase.c = testcase.ctxt.new_field (testcase.numeric_type, "c");
+ testcase.discriminant =
+ testcase.ctxt.new_field (testcase.numeric_type, "discriminant");
+ CHECK_STRING_VALUE (testcase.discriminant.get_debug_string ().c_str (),
+ "discriminant");
+ std::vector<gccjit::field> fields (4);
+ fields[0] = testcase.a;
+ fields[1] = testcase.b;
+ fields[2] = testcase.c;
+ fields[3] = testcase.discriminant;
+ testcase.quadratic =
+ testcase.ctxt.new_struct_type (
+ "quadratic",
+ fields);
+ testcase.quadratic_ptr = testcase.quadratic.get_pointer ();
+}
+
+static void
+make_sqrt (quadratic_test &testcase)
+{
+ std::vector<gccjit::param> params (1);
+ params[0] =
+ testcase.ctxt.new_param (testcase.numeric_type, "x");
+ testcase.sqrt =
+ testcase.ctxt.new_function (GCC_JIT_FUNCTION_IMPORTED,
+ testcase.numeric_type,
+ "sqrt",
+ params,
+ 0);
+}
+
+static void
+make_calc_discriminant (quadratic_test &testcase)
+{
+ /* Build "calc_discriminant". */
+ gccjit::param param_q =
+ testcase.ctxt.new_param (testcase.quadratic_ptr, "q");
+ std::vector <gccjit::param> params (1);
+ params[0] = param_q;
+ testcase.calc_discriminant =
+ testcase.ctxt.new_function (GCC_JIT_FUNCTION_EXPORTED,
+ testcase.numeric_type,
+ "calc_discriminant",
+ params,
+ 0);
+ testcase.calc_discriminant.add_comment ("(b^2 - 4ac)");
+
+ gccjit::rvalue q_a = param_q.dereference_field (testcase.a);
+ gccjit::rvalue q_b = param_q.dereference_field (testcase.b);
+ gccjit::rvalue q_c = param_q.dereference_field (testcase.c);
+
+ gccjit::rvalue four =
+ testcase.ctxt.new_rvalue (testcase.numeric_type, 4);
+
+ testcase.calc_discriminant.add_assignment (
+ /* q->discriminant =... */
+ param_q.dereference_field (testcase.discriminant),
+ /* (q->b * q->b) - (4 * q->a * q->c) */
+ (q_b * q_b) - (four * q_a * q_c));
+}
+
+static void
+make_test_quadratic (quadratic_test &testcase)
+{
+ gccjit::param a = testcase.ctxt.new_param (testcase.numeric_type, "a");
+ gccjit::param b = testcase.ctxt.new_param (testcase.numeric_type, "b");
+ gccjit::param c = testcase.ctxt.new_param (testcase.numeric_type, "c");
+ gccjit::param r1 =
+ testcase.ctxt.new_param (testcase.numeric_type_ptr, "r1");
+ gccjit::param r2 =
+ testcase.ctxt.new_param (testcase.numeric_type_ptr, "r2");
+
+ std::vector<gccjit::param> params (5);
+ params[0] = a;
+ params[1] = b;
+ params[2] = c;
+ params[3] = r1;
+ params[4] = r2;
+
+ gccjit::function test_quadratic =
+ testcase.ctxt.new_function (GCC_JIT_FUNCTION_EXPORTED,
+ testcase.int_type,
+ "test_quadratic",
+ params,
+ 0);
+
+ /* struct quadratic q; */
+ gccjit::lvalue q = test_quadratic.new_local (testcase.quadratic, "q");
+ /* q.a = a; */
+ test_quadratic.add_assignment (q.access_field (testcase.a), a);
+ /* q.b = b; */
+ test_quadratic.add_assignment (q.access_field (testcase.b), b);
+ /* q.c = c; */
+ test_quadratic.add_assignment (q.access_field (testcase.c), c);
+ /* calc_discriminant (&q); */
+ gccjit::rvalue address_of_q = q.get_address ();
+ test_quadratic.add_eval (testcase.calc_discriminant (address_of_q));
+
+ gccjit::label on_positive_discriminant
+ = test_quadratic.new_forward_label ("positive_discriminant");
+
+ gccjit::label on_nonpositive_discriminant
+ = test_quadratic.new_forward_label ("nonpositive_discriminant");
+
+ gccjit::label on_zero_discriminant
+ = test_quadratic.new_forward_label ("zero_discriminant");
+
+ gccjit::label on_negative_discriminant
+ = test_quadratic.new_forward_label ("negative_discriminant");
+ CHECK_STRING_VALUE (on_zero_discriminant.get_debug_string ().c_str (),
+ "zero_discriminant");
+
+ test_quadratic.add_comment ("if (q.discriminant > 0)");
+ test_quadratic.add_conditional (
+ q.access_field (testcase.discriminant) > testcase.zero,
+ on_positive_discriminant,
+ on_nonpositive_discriminant);
+
+ test_quadratic.place_forward_label (on_positive_discriminant);
+ /* double s = sqrt (q.discriminant); */
+ gccjit::lvalue s = test_quadratic.new_local (testcase.numeric_type, "s");
+ gccjit::rvalue discriminant_of_q = q.access_field (testcase.discriminant);
+ test_quadratic.add_assignment (s, testcase.sqrt (discriminant_of_q));
+
+ gccjit::rvalue minus_b = -b;
+ gccjit::rvalue two =
+ testcase.ctxt.new_rvalue (testcase.numeric_type, 2);
+ gccjit::rvalue two_a = two * a;
+ CHECK_STRING_VALUE (two_a.get_debug_string ().c_str (),
+ "(double)2 * a");
+
+ test_quadratic.add_comment ("*r1 = (-b + s) / (2 * a);");
+ test_quadratic.add_assignment (*r1, (minus_b + s) / two_a);
+
+ test_quadratic.add_comment ("*r2 = (-b - s) / (2 * a)");
+ test_quadratic.add_assignment (*r2, (minus_b - s) / two_a);
+
+ /* "return 2;" */
+ test_quadratic.add_return (testcase.ctxt.new_rvalue (testcase.int_type, 2));
+
+ /* "else if (q.discriminant == 0)" */
+ test_quadratic.place_forward_label (on_nonpositive_discriminant);
+ test_quadratic.add_comment ("else if (q.discriminant == 0)");
+ test_quadratic.add_conditional (
+ q.access_field (testcase.discriminant) == testcase.zero,
+ on_zero_discriminant,
+ on_negative_discriminant);
+
+ /* if (q.discriminant == 0) */
+ test_quadratic.place_forward_label (on_zero_discriminant);
+
+ test_quadratic.add_comment ("*r1 = -b / (2 * a);");
+ test_quadratic.add_assignment (*r1, minus_b / two_a);
+
+ /* "return 1;" */
+ test_quadratic.add_return (testcase.ctxt.one (testcase.int_type));
+
+ /* else return 0; */
+ test_quadratic.place_forward_label (on_negative_discriminant);
+ test_quadratic.add_return (testcase.ctxt.zero (testcase.int_type));
+
+ /* Verify that output stream operator << works. */
+ std::ostringstream os;
+ os << "streamed output: " << address_of_q;
+ CHECK_STRING_VALUE (os.str ().c_str (), "streamed output: &q");
+}
+
+void
+create_code (gcc_jit_context *ctxt, void *user_data)
+{
+ struct quadratic_test testcase;
+ memset (&testcase, 0, sizeof (testcase));
+ testcase.ctxt = ctxt;
+ make_types (testcase);
+ make_sqrt (testcase);
+ make_calc_discriminant (testcase);
+ make_test_quadratic (testcase);
+}
+
+void
+verify_code (gcc_jit_context *ctxt, gcc_jit_result *result)
+{
+ typedef int (*fn_type) (double a, double b, double c,
+ double *r1, double *r2);
+
+ CHECK_NON_NULL (result);
+
+ fn_type test_quadratic =
+ (fn_type)gcc_jit_result_get_code (result, "test_quadratic");
+ CHECK_NON_NULL (test_quadratic);
+
+ /* Verify that the code correctly solves quadratic equations. */
+ double r1, r2;
+
+ /* This one has two solutions: */
+ CHECK_VALUE (test_quadratic (1, 3, -4, &r1, &r2), 2);
+ CHECK_VALUE (r1, 1);
+ CHECK_VALUE (r2, -4);
+
+ /* This one has one solution: */
+ CHECK_VALUE (test_quadratic (4, 4, 1, &r1, &r2), 1);
+ CHECK_VALUE (r1, -0.5);
+
+ /* This one has no real solutions: */
+ CHECK_VALUE (test_quadratic (4, 1, 1, &r1, &r2), 0);
+}
--
1.7.11.7