I've committed the following to dmalcolm/jit: Add unary ops. Add more binary ops. Add more comparison modes. Convert field access API from:
extern gcc_jit_lvalue * gcc_jit_context_new_field_access (gcc_jit_context *ctxt, gcc_jit_location *loc, gcc_jit_rvalue *ptr_or_struct, const char *fieldname); to: /* Accessing a field of an lvalue of struct type, analogous to: (EXPR).field = ...; in C. */ extern gcc_jit_lvalue * gcc_jit_lvalue_access_field (gcc_jit_lvalue *struct_, gcc_jit_location *loc, const char *fieldname); /* Accessing a field of an rvalue of struct type, analogous to: (EXPR).field in C. */ extern gcc_jit_rvalue * gcc_jit_rvalue_access_field (gcc_jit_rvalue *struct_, gcc_jit_location *loc, const char *fieldname); /* Accessing a field of an rvalue of pointer type, analogous to: (EXPR)->field in C, itself equivalent to (*EXPR).FIELD */ extern gcc_jit_lvalue * gcc_jit_rvalue_dereference_field (gcc_jit_rvalue *ptr, gcc_jit_location *loc, const char *fieldname); /* Dereferencing a pointer; analogous to: *(EXPR) */ extern gcc_jit_lvalue * gcc_jit_rvalue_dereference (gcc_jit_rvalue *rvalue, gcc_jit_location *loc); gcc/jit/ * internal-api.c (gcc::jit::context::new_param): Add context argument to ctor for rvalue and its subclasses. (gcc::jit::context::new_global): Likewise. (gcc::jit::context::new_rvalue_from_int): Likewise. (gcc::jit::context::new_rvalue_from_double): Likewise. (gcc::jit::context::new_rvalue_from_ptr): Likewise. (gcc::jit::context::new_string_literal): Likewise. (gcc::jit::context::new_call): Likewise. (gcc::jit::context::new_array_lookup): Likewise. (gcc::jit::function::new_local): Likewise. (gcc::jit::context::new_binary_op): Likewise; add new operations. (gcc::jit::context::new_comparison): Likewise; add new comparisons. (gcc::jit::context::as_truth_value): New. (gcc::jit::context::new_unary_op): New. (gcc::jit::context::new_field_access): Convert to a helper method for use by the access_fields methods. (gcc::jit::context::new_dereference): New. (gcc::jit::lvalue::access_field): New. (gcc::jit::rvalue::access_field): New. (gcc::jit::rvalue::dereference_field): New. (gcc::jit::rvalue::dereference): New. * internal-api.h (gcc::jit::context::new_unary_op): New. (gcc::jit::context::new_field_access): Work (gcc::jit::context::new_dereference): New. (gcc::jit::context::as_truth_value): New. (gcc::jit::rvalue): Add a context field. (gcc::jit::rvalue::access_field): New. (gcc::jit::rvalue::dereference_field): New. (gcc::jit::rvalue::dereference): New. (gcc::jit::lvalue::lvalue): Add context to ctor. (gcc::jit::lvalue::access_field): New. (gcc::jit::param::param): Add context to ctor. * libgccjit.c (gcc_jit_context_new_unary_op): New. (gcc_jit_context_new_field_access): Remove. (gcc_jit_lvalue_access_field): New. (gcc_jit_rvalue_access_field): New. (gcc_jit_rvalue_dereference_field): New. (gcc_jit_rvalue_dereference): New. *libgccjit.h (enum gcc_jit_unary_op): New. (gcc_jit_context_new_unary_op): New. (enum gcc_jit_binary_op): Document values, and add... (GCC_JIT_BINARY_OP_DIVIDE): New. (GCC_JIT_BINARY_OP_MODULO): New. (GCC_JIT_BINARY_OP_BITWISE_AND): New. (GCC_JIT_BINARY_OP_BITWISE_XOR): New. (GCC_JIT_BINARY_OP_BITWISE_OR): New. (GCC_JIT_BINARY_OP_LOGICAL_AND): New. (GCC_JIT_BINARY_OP_LOGICAL_OR): New. (enum gcc_jit_comparison): Document values, and add... (GCC_JIT_COMPARISON_EQ): New. (GCC_JIT_COMPARISON_NE): New. (GCC_JIT_COMPARISON_LE): New. (GCC_JIT_COMPARISON_GT): New. (GCC_JIT_COMPARISON_GE): New. (gcc_jit_context_new_field_access): Remove. (gcc_jit_lvalue_access_field): New. (gcc_jit_rvalue_access_field): New. (gcc_jit_rvalue_dereference_field): New. (gcc_jit_rvalue_dereference): New. * libgccjit.map (gcc_jit_context_new_field_access): Remove. (gcc_jit_lvalue_access_field): New. (gcc_jit_rvalue_access_field): New. (gcc_jit_rvalue_dereference_field): New. (gcc_jit_rvalue_dereference): New. * TODO.rst: Update gcc/testsuite/ * jit.dg/test-expressions.c: New. * jit.dg/test-combination.c: Add usage of test-expressions.c * jit.dg/test-accessing-struct.c (code_making_callback): Update for changes to field-access API. * jit.dg/test-types.c (code_making_callback): Likewise. --- gcc/jit/ChangeLog.jit | 70 ++++ gcc/jit/TODO.rst | 24 +- gcc/jit/internal-api.c | 224 ++++++++++-- gcc/jit/internal-api.h | 54 ++- gcc/jit/libgccjit.c | 58 ++- gcc/jit/libgccjit.h | 125 ++++++- gcc/jit/libgccjit.map | 6 +- gcc/testsuite/ChangeLog.jit | 8 + gcc/testsuite/jit.dg/test-accessing-struct.c | 20 +- gcc/testsuite/jit.dg/test-combination.c | 9 + gcc/testsuite/jit.dg/test-expressions.c | 518 +++++++++++++++++++++++++++ gcc/testsuite/jit.dg/test-types.c | 4 +- 12 files changed, 1043 insertions(+), 77 deletions(-) create mode 100644 gcc/testsuite/jit.dg/test-expressions.c diff --git a/gcc/jit/ChangeLog.jit b/gcc/jit/ChangeLog.jit index bcbb93b..7c574e8 100644 --- a/gcc/jit/ChangeLog.jit +++ b/gcc/jit/ChangeLog.jit @@ -1,5 +1,75 @@ 2013-10-18 David Malcolm <dmalc...@redhat.com> + * internal-api.c (gcc::jit::context::new_param): Add context + argument to ctor for rvalue and its subclasses. + (gcc::jit::context::new_global): Likewise. + (gcc::jit::context::new_rvalue_from_int): Likewise. + (gcc::jit::context::new_rvalue_from_double): Likewise. + (gcc::jit::context::new_rvalue_from_ptr): Likewise. + (gcc::jit::context::new_string_literal): Likewise. + (gcc::jit::context::new_call): Likewise. + (gcc::jit::context::new_array_lookup): Likewise. + (gcc::jit::function::new_local): Likewise. + (gcc::jit::context::new_binary_op): Likewise; add new + operations. + (gcc::jit::context::new_comparison): Likewise; add new + comparisons. + (gcc::jit::context::as_truth_value): New. + (gcc::jit::context::new_unary_op): New. + (gcc::jit::context::new_field_access): Convert to a helper + method for use by the access_fields methods. + (gcc::jit::context::new_dereference): New. + (gcc::jit::lvalue::access_field): New. + (gcc::jit::rvalue::access_field): New. + (gcc::jit::rvalue::dereference_field): New. + (gcc::jit::rvalue::dereference): New. + * internal-api.h (gcc::jit::context::new_unary_op): New. + (gcc::jit::context::new_field_access): Work + (gcc::jit::context::new_dereference): New. + (gcc::jit::context::as_truth_value): New. + (gcc::jit::rvalue): Add a context field. + (gcc::jit::rvalue::access_field): New. + (gcc::jit::rvalue::dereference_field): New. + (gcc::jit::rvalue::dereference): New. + (gcc::jit::lvalue::lvalue): Add context to ctor. + (gcc::jit::lvalue::access_field): New. + (gcc::jit::param::param): Add context to ctor. + * libgccjit.c (gcc_jit_context_new_unary_op): New. + (gcc_jit_context_new_field_access): Remove. + (gcc_jit_lvalue_access_field): New. + (gcc_jit_rvalue_access_field): New. + (gcc_jit_rvalue_dereference_field): New. + (gcc_jit_rvalue_dereference): New. + *libgccjit.h (enum gcc_jit_unary_op): New. + (gcc_jit_context_new_unary_op): New. + (enum gcc_jit_binary_op): Document values, and add... + (GCC_JIT_BINARY_OP_DIVIDE): New. + (GCC_JIT_BINARY_OP_MODULO): New. + (GCC_JIT_BINARY_OP_BITWISE_AND): New. + (GCC_JIT_BINARY_OP_BITWISE_XOR): New. + (GCC_JIT_BINARY_OP_BITWISE_OR): New. + (GCC_JIT_BINARY_OP_LOGICAL_AND): New. + (GCC_JIT_BINARY_OP_LOGICAL_OR): New. + (enum gcc_jit_comparison): Document values, and add... + (GCC_JIT_COMPARISON_EQ): New. + (GCC_JIT_COMPARISON_NE): New. + (GCC_JIT_COMPARISON_LE): New. + (GCC_JIT_COMPARISON_GT): New. + (GCC_JIT_COMPARISON_GE): New. + (gcc_jit_context_new_field_access): Remove. + (gcc_jit_lvalue_access_field): New. + (gcc_jit_rvalue_access_field): New. + (gcc_jit_rvalue_dereference_field): New. + (gcc_jit_rvalue_dereference): New. + * libgccjit.map (gcc_jit_context_new_field_access): Remove. + (gcc_jit_lvalue_access_field): New. + (gcc_jit_rvalue_access_field): New. + (gcc_jit_rvalue_dereference_field): New. + (gcc_jit_rvalue_dereference): New. + * TODO.rst: Update + +2013-10-18 David Malcolm <dmalc...@redhat.com> + * internal-api.c (gcc::jit::context::get_type): Improve error message, and report the bogus value. (gcc::jit::context::new_binary_op): Likewise. diff --git a/gcc/jit/TODO.rst b/gcc/jit/TODO.rst index ffe4c37..41cc4ad 100644 --- a/gcc/jit/TODO.rst +++ b/gcc/jit/TODO.rst @@ -24,19 +24,6 @@ Initial Release * how do you encode "x[5]=y;"? should gcc_jit_context_new_array_lookup() return an lvalue rather than an rvalue? -* separate out "x->field" from "x.field": - (x.field) = ...; : (lvalue, str) -> lvalue - ... = (x.field); : (rvalue, str) -> rvalue - (x->field) = ...; : (lvalue, str) -> lvalue - ... = (x->field); : (rvalue, str) -> rvalue - -* explicit dereferencing:: - - extern gcc_jit_lvalue * - gcc_jit_rvalue_dereference (gcc_jit_rvalue *); - - for e.g. *ptr = 42; - * explicit casts:: extern gcc_jit_rvalue * @@ -110,6 +97,10 @@ Initial Release * valgrind; fix memory leaks +* do we need alternative forms of division (floor vs rounding)? + +* are we missing any ops? + Future milestones ================= @@ -121,4 +112,11 @@ Future milestones * measure code coverage in testing of libgccjit.so +* "switch" and "case" ? + +* do we need unary plus? +* shift operators? +* sizeof (should this be an API hook?) do we even need it? presumably + client code can just do the sizeof() in its own code. + etc etc diff --git a/gcc/jit/internal-api.c b/gcc/jit/internal-api.c index c5376a3..81178e1 100644 --- a/gcc/jit/internal-api.c +++ b/gcc/jit/internal-api.c @@ -210,7 +210,7 @@ new_param (location *loc, if (loc) set_tree_location (inner, loc); - return new param (inner); + return new param (this, inner); } gcc::jit::function * @@ -298,7 +298,7 @@ new_global (location *loc, if (loc) set_tree_location (inner, loc); - return new lvalue (inner); + return new lvalue (this, inner); } gcc::jit::rvalue * @@ -311,14 +311,14 @@ new_rvalue_from_int (type *type, if (INTEGRAL_TYPE_P (inner_type)) { tree inner = build_int_cst (inner_type, value); - return new rvalue (inner); + return new rvalue (this, inner); } else { REAL_VALUE_TYPE real_value; real_from_integer (&real_value, VOIDmode, value, 0, 0); tree inner = build_real (inner_type, real_value); - return new rvalue (inner); + return new rvalue (this, inner); } } @@ -347,7 +347,7 @@ new_rvalue_from_double (type *type, as_long_ints[1] = u.as_uint32s[1]; real_from_target (&real_value, as_long_ints, DFmode); tree inner = build_real (inner_type, real_value); - return new rvalue (inner); + return new rvalue (this, inner); } gcc::jit::rvalue * @@ -358,7 +358,7 @@ new_rvalue_from_ptr (type *type, tree inner_type = type->as_tree (); /* FIXME: how to ensure we have a wide enough type? */ tree inner = build_int_cstu (inner_type, (unsigned HOST_WIDE_INT)value); - return new rvalue (inner); + return new rvalue (this, inner); } gcc::jit::rvalue * @@ -374,7 +374,72 @@ new_string_literal (const char *value) by taking address of start of string. */ tree t_addr = build1 (ADDR_EXPR, m_const_char_ptr, t_str); - return new rvalue (t_addr); + return new rvalue (this, t_addr); +} + +tree +gcc::jit::context:: +as_truth_value (tree expr, location *loc) +{ + /* Compare to c-typeck.c:c_objc_common_truthvalue_conversion */ + tree typed_zero = fold_build1 (CONVERT_EXPR, + TREE_TYPE (expr), + integer_zero_node); + if (loc) + set_tree_location (typed_zero, loc); + + expr = build2 (NE_EXPR, integer_type_node, expr, typed_zero); + if (loc) + set_tree_location (expr, loc); + + return expr; +} + +gcc::jit::rvalue * +gcc::jit::context:: +new_unary_op (location *loc, + enum gcc_jit_unary_op op, + type *result_type, + rvalue *a) +{ + // FIXME: type-checking, or coercion? + enum tree_code inner_op; + + gcc_assert (result_type); + gcc_assert (a); + + tree node = a->as_tree (); + tree inner_result = NULL; + + switch (op) + { + default: + add_error ("unrecognized (enum gcc_jit_unary_op) value: %i", op); + return NULL; + + case GCC_JIT_UNARY_OP_MINUS: + inner_op = NEGATE_EXPR; + break; + + case GCC_JIT_UNARY_OP_BITWISE_NEGATE: + inner_op = BIT_NOT_EXPR; + break; + + case GCC_JIT_UNARY_OP_LOGICAL_NEGATE: + node = as_truth_value (node, loc); + inner_result = invert_truthvalue (node); + if (loc) + set_tree_location (inner_result, loc); + return new rvalue (this, inner_result); + } + + inner_result = build1 (inner_op, + result_type->as_tree (), + node); + if (loc) + set_tree_location (inner_result, loc); + + return new rvalue (this, inner_result); } gcc::jit::rvalue * @@ -391,6 +456,9 @@ new_binary_op (location *loc, gcc_assert (a); gcc_assert (b); + tree node_a = a->as_tree (); + tree node_b = b->as_tree (); + switch (op) { default: @@ -408,16 +476,49 @@ new_binary_op (location *loc, case GCC_JIT_BINARY_OP_MULT: inner_op = MULT_EXPR; break; + + case GCC_JIT_BINARY_OP_DIVIDE: + inner_op = TRUNC_DIV_EXPR; + break; + /* do we want separate floor divide vs frac divide? */ + + case GCC_JIT_BINARY_OP_MODULO: + inner_op = TRUNC_MOD_EXPR; + break; + + case GCC_JIT_BINARY_OP_BITWISE_AND: + inner_op = BIT_AND_EXPR; + break; + + case GCC_JIT_BINARY_OP_BITWISE_XOR: + inner_op = BIT_XOR_EXPR; + break; + + case GCC_JIT_BINARY_OP_BITWISE_OR: + inner_op = BIT_IOR_EXPR; + break; + + case GCC_JIT_BINARY_OP_LOGICAL_AND: + node_a = as_truth_value (node_a, loc); + node_b = as_truth_value (node_b, loc); + inner_op = TRUTH_ANDIF_EXPR; + break; + + case GCC_JIT_BINARY_OP_LOGICAL_OR: + node_a = as_truth_value (node_a, loc); + node_b = as_truth_value (node_b, loc); + inner_op = TRUTH_ORIF_EXPR; + break; } tree inner_expr = build2 (inner_op, result_type->as_tree (), - a->as_tree (), - b->as_tree ()); + node_a, + node_b); if (loc) set_tree_location (inner_expr, loc); - return new rvalue (inner_expr); + return new rvalue (this, inner_expr); } gcc::jit::rvalue * @@ -438,9 +539,21 @@ new_comparison (location *loc, add_error ("unrecognized (enum gcc_jit_comparison) value: %i", op); return NULL; + case GCC_JIT_COMPARISON_EQ: + inner_op = EQ_EXPR; + break; + case GCC_JIT_COMPARISON_NE: + inner_op = NE_EXPR; + break; case GCC_JIT_COMPARISON_LT: inner_op = LT_EXPR; break; + case GCC_JIT_COMPARISON_LE: + inner_op = LE_EXPR; + break; + case GCC_JIT_COMPARISON_GT: + inner_op = GT_EXPR; + break; case GCC_JIT_COMPARISON_GE: inner_op = GE_EXPR; break; @@ -452,7 +565,7 @@ new_comparison (location *loc, b->as_tree ()); if (loc) set_tree_location (inner_expr, loc); - return new rvalue (inner_expr); + return new rvalue (this, inner_expr); } gcc::jit::rvalue * @@ -483,7 +596,8 @@ new_call (location *loc, if (loc) set_tree_location (fn, loc); - return new rvalue (build_call_vec (func->get_return_type_as_tree (), + return new rvalue (this, + build_call_vec (func->get_return_type_as_tree (), fn, tree_args)); /* see c-typeck.c: build_function_call @@ -521,7 +635,7 @@ new_array_lookup (location *loc, NULL_TREE, NULL_TREE); if (loc) set_tree_location (t_result, loc); - return new rvalue (t_result); + return new rvalue (this, t_result); } else { @@ -542,7 +656,7 @@ new_array_lookup (location *loc, set_tree_location (t_indirection, loc); } - return new rvalue (t_indirection); + return new rvalue (this, t_indirection); } } @@ -555,40 +669,92 @@ get_field (tree type, tree component) return NULL; } -gcc::jit::lvalue * +tree gcc::jit::context:: new_field_access (location *loc, - rvalue *ptr_or_struct, + tree datum, const char *fieldname) { - gcc_assert (ptr_or_struct); + gcc_assert (datum); gcc_assert (fieldname); /* Compare with c/ctypeck.c:lookup_field, build_indirect_ref, and build_component_ref. */ - tree datum = ptr_or_struct->as_tree (); tree type = TREE_TYPE (datum); - - if (TREE_CODE (type) == POINTER_TYPE) - { - datum = build1 (INDIRECT_REF, type, datum); - if (loc) - set_tree_location (datum, loc); - type = TREE_TYPE (type); - } + gcc_assert (TREE_CODE (type) != POINTER_TYPE); tree component = get_identifier (fieldname); tree field = get_field (type, component); if (!field) { - // FIXME: field not found + add_error ("field not found: \"%s\"", fieldname); return NULL; } tree ref = build3 (COMPONENT_REF, TREE_TYPE (field), datum, field, NULL_TREE); if (loc) set_tree_location (ref, loc); - return new lvalue (ref); + return ref; +} + +tree +gcc::jit::context:: +new_dereference (tree ptr, + location *loc) +{ + gcc_assert (ptr); + + tree type = TREE_TYPE (TREE_TYPE(ptr)); + tree datum = build1 (INDIRECT_REF, type, ptr); + if (loc) + set_tree_location (datum, loc); + return datum; +} + +gcc::jit::lvalue * +gcc::jit::lvalue:: +access_field (location *loc, + const char *fieldname) +{ + tree datum = as_tree (); + tree ref = get_context ()->new_field_access (loc, datum, fieldname); + if (!ref) + return NULL; + return new lvalue (get_context (), ref); +} + +gcc::jit::rvalue * +gcc::jit::rvalue:: +access_field (gcc::jit::location *loc, + const char *fieldname) +{ + tree datum = as_tree (); + tree ref = get_context ()->new_field_access (loc, datum, fieldname); + if (!ref) + return NULL; + return new rvalue (get_context (), ref); +} + +gcc::jit::lvalue * +gcc::jit::rvalue:: +dereference_field (gcc::jit::location *loc, + const char *fieldname) +{ + tree ptr = as_tree (); + tree datum = get_context ()->new_dereference (ptr, loc); + tree ref = get_context ()->new_field_access (loc, datum, fieldname); + if (!ref) + return NULL; + return new lvalue (get_context (), ref); +} + +gcc::jit::lvalue * +gcc::jit::rvalue:: +dereference (gcc::jit::location *loc) +{ + tree ptr = as_tree (); + tree datum = get_context ()->new_dereference (ptr, loc); + return new lvalue (get_context (), datum); } void * @@ -643,7 +809,7 @@ new_local (location *loc, type->as_tree ()); if (loc) set_tree_location (inner, loc); - return new lvalue (inner); + return new lvalue (m_ctxt, inner); } gcc::jit::label * diff --git a/gcc/jit/internal-api.h b/gcc/jit/internal-api.h index 6665e65..e31dbc8 100644 --- a/gcc/jit/internal-api.h +++ b/gcc/jit/internal-api.h @@ -97,6 +97,12 @@ public: new_string_literal (const char *value); rvalue * + new_unary_op (location *loc, + enum gcc_jit_unary_op op, + type *result_type, + rvalue *a); + + rvalue * new_binary_op (location *loc, enum gcc_jit_binary_op op, type *result_type, @@ -117,11 +123,6 @@ public: rvalue *ptr, rvalue *index); - lvalue * - new_field_access (location *loc, - rvalue *ptr_or_struct, - const char *fieldname); - void set_str_option (enum gcc_jit_str_option opt, const char *value); @@ -160,6 +161,17 @@ public: void set_tree_location (tree t, location *loc); + tree + new_field_access (location *loc, + tree datum, + const char *fieldname); + + tree + new_dereference (tree ptr, location *loc); + + tree + as_truth_value (tree expr, location *loc); + private: source_file * get_source_file (const char *filename); @@ -365,8 +377,9 @@ public: // for now class rvalue : public wrapper { public: - rvalue (tree inner) - : m_inner(inner) + rvalue (context *ctxt, tree inner) + : m_ctxt (ctxt), + m_inner (inner) {} rvalue * @@ -374,29 +387,48 @@ public: tree as_tree () const { return m_inner; } + context *get_context () const { return m_ctxt; } + type * get_type () { return new type (TREE_TYPE (m_inner)); } + rvalue * + access_field (location *loc, + const char *fieldname); + + lvalue * + dereference_field (location *loc, + const char *fieldname); + + lvalue * + dereference (location *loc); + private: + context *m_ctxt; tree m_inner; }; class lvalue : public rvalue { public: - lvalue (tree inner) - : rvalue(inner) + lvalue (context *ctxt, tree inner) + : rvalue(ctxt, inner) {} lvalue * as_lvalue () { return this; } + + lvalue * + access_field (location *loc, + const char *fieldname); + }; class param : public lvalue { public: - param (tree inner) - : lvalue(inner) + param (context *ctxt, tree inner) + : lvalue(ctxt, inner) {} }; diff --git a/gcc/jit/libgccjit.c b/gcc/jit/libgccjit.c index 05afd8e..023c213 100644 --- a/gcc/jit/libgccjit.c +++ b/gcc/jit/libgccjit.c @@ -413,6 +413,21 @@ gcc_jit_context_new_string_literal (gcc_jit_context *ctxt, } gcc_jit_rvalue * +gcc_jit_context_new_unary_op (gcc_jit_context *ctxt, + gcc_jit_location *loc, + enum gcc_jit_unary_op op, + gcc_jit_type *result_type, + gcc_jit_rvalue *rvalue) +{ + RETURN_NULL_IF_NOT_CALLBACK_CTXT (ctxt); + /* op is checked by the inner function. */ + RETURN_NULL_IF_FAIL (result_type, ctxt, "NULL result_type"); + RETURN_NULL_IF_FAIL (rvalue, ctxt, "NULL rvalue"); + + return (gcc_jit_rvalue *)ctxt->new_unary_op (loc, op, result_type, rvalue); +} + +gcc_jit_rvalue * gcc_jit_context_new_binary_op (gcc_jit_context *ctxt, gcc_jit_location *loc, enum gcc_jit_binary_op op, @@ -472,17 +487,46 @@ gcc_jit_context_new_array_lookup (gcc_jit_context *ctxt, return (gcc_jit_rvalue *)ctxt->new_array_lookup (loc, ptr, index); } -extern gcc_jit_lvalue * -gcc_jit_context_new_field_access (gcc_jit_context *ctxt, +gcc_jit_lvalue * +gcc_jit_lvalue_access_field (gcc_jit_lvalue *struct_, + gcc_jit_location *loc, + const char *fieldname) +{ + RETURN_NULL_IF_FAIL (struct_, NULL, "NULL struct"); + RETURN_NULL_IF_FAIL (fieldname, NULL, "NULL fieldname"); + + return (gcc_jit_lvalue *)struct_->access_field (loc, fieldname); +} + +gcc_jit_rvalue * +gcc_jit_rvalue_access_field (gcc_jit_rvalue *struct_, + gcc_jit_location *loc, + const char *fieldname) +{ + RETURN_NULL_IF_FAIL (struct_, NULL, "NULL struct"); + RETURN_NULL_IF_FAIL (fieldname, NULL, "NULL fieldname"); + + return (gcc_jit_rvalue *)struct_->access_field (loc, fieldname); +} + +gcc_jit_lvalue * +gcc_jit_rvalue_dereference_field (gcc_jit_rvalue *ptr, gcc_jit_location *loc, - gcc_jit_rvalue *ptr_or_struct, const char *fieldname) { - RETURN_NULL_IF_NOT_CALLBACK_CTXT (ctxt); - RETURN_NULL_IF_FAIL (ptr_or_struct, ctxt, "NULL ptr_or_struct"); - RETURN_NULL_IF_FAIL (fieldname, ctxt, "NULL fieldname"); + RETURN_NULL_IF_FAIL (ptr, NULL, "NULL ptr"); + RETURN_NULL_IF_FAIL (fieldname, NULL, "NULL fieldname"); + + return (gcc_jit_lvalue *)ptr->dereference_field (loc, fieldname); +} + +gcc_jit_lvalue * +gcc_jit_rvalue_dereference (gcc_jit_rvalue *rvalue, + gcc_jit_location *loc) +{ + RETURN_NULL_IF_FAIL (rvalue, NULL, "NULL rvalue"); - return (gcc_jit_lvalue *)ctxt->new_field_access (loc, ptr_or_struct, fieldname); + return (gcc_jit_lvalue *)rvalue->dereference (loc); } gcc_jit_lvalue * diff --git a/gcc/jit/libgccjit.h b/gcc/jit/libgccjit.h index 78d3904..2187ede 100644 --- a/gcc/jit/libgccjit.h +++ b/gcc/jit/libgccjit.h @@ -438,12 +438,85 @@ extern gcc_jit_rvalue * gcc_jit_context_new_string_literal (gcc_jit_context *ctxt, const char *value); +enum gcc_jit_unary_op +{ + /* Negate an arithmetic value; analogous to: + -(EXPR) + in C. */ + GCC_JIT_UNARY_OP_MINUS, + + /* Bitwise negation of an integer value (one's complement); analogous + to: + ~(EXPR) + in C. */ + GCC_JIT_UNARY_OP_BITWISE_NEGATE, + + /* Logical negation of an arithmetic or pointer value; analogous to: + !(EXPR) + in C. */ + GCC_JIT_UNARY_OP_LOGICAL_NEGATE +}; + +extern gcc_jit_rvalue * +gcc_jit_context_new_unary_op (gcc_jit_context *ctxt, + gcc_jit_location *loc, + enum gcc_jit_unary_op op, + gcc_jit_type *result_type, + gcc_jit_rvalue *rvalue); enum gcc_jit_binary_op { + /* Addition of arithmetic values; analogous to: + (EXPR_A) + (EXPR_B) + in C. + For pointer addition, use gcc_jit_context_new_array_lookup. */ GCC_JIT_BINARY_OP_PLUS, + + /* Subtraction of arithmetic values; analogous to: + (EXPR_A) - (EXPR_B) + in C. */ GCC_JIT_BINARY_OP_MINUS, - GCC_JIT_BINARY_OP_MULT + + /* Multiplication of a pair of arithmetic values; analogous to: + (EXPR_A) * (EXPR_B) + in C. */ + GCC_JIT_BINARY_OP_MULT, + + /* Quotient of division of arithmetic values; analogous to: + (EXPR_A) / (EXPR_B) + in C. */ + GCC_JIT_BINARY_OP_DIVIDE, + /* do we want separate floor divide vs frac divide? */ + + /* Remainder of division of arithmetic values; analogous to: + (EXPR_A) / (EXPR_B) + in C. */ + GCC_JIT_BINARY_OP_MODULO, + + /* Bitwise AND; analogous to: + (EXPR_A) & (EXPR_B) + in C. */ + GCC_JIT_BINARY_OP_BITWISE_AND, + + /* Bitwise exclusive OR; analogous to: + (EXPR_A) ^ (EXPR_B) + in C. */ + GCC_JIT_BINARY_OP_BITWISE_XOR, + + /* Bitwise inclusive OR; analogous to: + (EXPR_A) | (EXPR_B) + in C. */ + GCC_JIT_BINARY_OP_BITWISE_OR, + + /* Logical AND; analogous to: + (EXPR_A) && (EXPR_B) + in C. */ + GCC_JIT_BINARY_OP_LOGICAL_AND, + + /* Logical OR; analogous to: + (EXPR_A) || (EXPR_B) + in C. */ + GCC_JIT_BINARY_OP_LOGICAL_OR }; extern gcc_jit_rvalue * @@ -453,9 +526,27 @@ gcc_jit_context_new_binary_op (gcc_jit_context *ctxt, gcc_jit_type *result_type, gcc_jit_rvalue *a, gcc_jit_rvalue *b); +/* (Comparisons are treated as separate from "binary_op" to save + you having to specify the result_type). */ + enum gcc_jit_comparison { + /* (EXPR_A) == (EXPR_B). */ + GCC_JIT_COMPARISON_EQ, + + /* (EXPR_A) != (EXPR_B). */ + GCC_JIT_COMPARISON_NE, + + /* (EXPR_A) < (EXPR_B). */ GCC_JIT_COMPARISON_LT, + + /* (EXPR_A) <=(EXPR_B). */ + GCC_JIT_COMPARISON_LE, + + /* (EXPR_A) > (EXPR_B). */ + GCC_JIT_COMPARISON_GT, + + /* (EXPR_A) >= (EXPR_B). */ GCC_JIT_COMPARISON_GE }; @@ -477,13 +568,39 @@ gcc_jit_context_new_array_lookup (gcc_jit_context *ctxt, gcc_jit_rvalue *ptr, gcc_jit_rvalue *index); -/* Field access, either s.field or s->field. */ +/* Field access is provided separately for both lvalues and rvalues. */ + +/* Accessing a field of an lvalue of struct type, analogous to: + (EXPR).field = ...; + in C. */ extern gcc_jit_lvalue * -gcc_jit_context_new_field_access (gcc_jit_context *ctxt, +gcc_jit_lvalue_access_field (gcc_jit_lvalue *struct_, + gcc_jit_location *loc, + const char *fieldname); + +/* Accessing a field of an rvalue of struct type, analogous to: + (EXPR).field + in C. */ +extern gcc_jit_rvalue * +gcc_jit_rvalue_access_field (gcc_jit_rvalue *struct_, + gcc_jit_location *loc, + const char *fieldname); + +/* Accessing a field of an rvalue of pointer type, analogous to: + (EXPR)->field + in C, itself equivalent to (*EXPR).FIELD */ +extern gcc_jit_lvalue * +gcc_jit_rvalue_dereference_field (gcc_jit_rvalue *ptr, gcc_jit_location *loc, - gcc_jit_rvalue *ptr_or_struct, const char *fieldname); +/* Dereferencing a pointer; analogous to: + *(EXPR) +*/ +extern gcc_jit_lvalue * +gcc_jit_rvalue_dereference (gcc_jit_rvalue *rvalue, + gcc_jit_location *loc); + extern gcc_jit_lvalue * gcc_jit_function_new_local (gcc_jit_function *func, gcc_jit_location *loc, diff --git a/gcc/jit/libgccjit.map b/gcc/jit/libgccjit.map index beaf0de..7700788 100644 --- a/gcc/jit/libgccjit.map +++ b/gcc/jit/libgccjit.map @@ -10,7 +10,6 @@ gcc_jit_context_new_call; gcc_jit_context_new_comparison; gcc_jit_context_new_field; - gcc_jit_context_new_field_access; gcc_jit_context_new_function; gcc_jit_context_new_global; gcc_jit_context_new_location; @@ -20,6 +19,7 @@ gcc_jit_context_new_rvalue_from_ptr; gcc_jit_context_new_string_literal; gcc_jit_context_new_struct_type; + gcc_jit_context_new_unary_op; gcc_jit_context_one; gcc_jit_context_release; gcc_jit_context_set_bool_option; @@ -40,10 +40,14 @@ gcc_jit_function_place_forward_label; gcc_jit_loop_end; gcc_jit_lvalue_as_rvalue; + gcc_jit_lvalue_access_field; gcc_jit_param_as_lvalue; gcc_jit_param_as_rvalue; gcc_jit_result_get_code; gcc_jit_result_release; + gcc_jit_rvalue_access_field; + gcc_jit_rvalue_dereference; + gcc_jit_rvalue_dereference_field; gcc_jit_type_get_const; gcc_jit_type_get_pointer; diff --git a/gcc/testsuite/ChangeLog.jit b/gcc/testsuite/ChangeLog.jit index b23c8fc..987353d 100644 --- a/gcc/testsuite/ChangeLog.jit +++ b/gcc/testsuite/ChangeLog.jit @@ -1,5 +1,13 @@ 2013-10-18 David Malcolm <dmalc...@redhat.com> + * jit.dg/test-expressions.c: New. + * jit.dg/test-combination.c: Add usage of test-expressions.c + * jit.dg/test-accessing-struct.c (code_making_callback): Update + for changes to field-access API. + * jit.dg/test-types.c (code_making_callback): Likewise. + +2013-10-18 David Malcolm <dmalc...@redhat.com> + * jit.dg/test-null-passed-to-api.c: New. 2013-10-17 David Malcolm <dmalc...@redhat.com> diff --git a/gcc/testsuite/jit.dg/test-accessing-struct.c b/gcc/testsuite/jit.dg/test-accessing-struct.c index 46f112a..4e197c5 100644 --- a/gcc/testsuite/jit.dg/test-accessing-struct.c +++ b/gcc/testsuite/jit.dg/test-accessing-struct.c @@ -64,23 +64,23 @@ code_making_callback (gcc_jit_context *ctxt, void *user_data) GCC_JIT_BINARY_OP_MULT, int_type, gcc_jit_lvalue_as_rvalue ( - gcc_jit_context_new_field_access ( - ctxt, NULL, - gcc_jit_param_as_rvalue (param_f), - "x")), + gcc_jit_rvalue_dereference_field ( + gcc_jit_param_as_rvalue (param_f), + NULL, + "x")), gcc_jit_lvalue_as_rvalue ( - gcc_jit_context_new_field_access ( - ctxt, NULL, - gcc_jit_param_as_rvalue (param_f), - "y"))); + gcc_jit_rvalue_dereference_field ( + gcc_jit_param_as_rvalue (param_f), + NULL, + "y"))); /* f->z = ... */ gcc_jit_function_add_assignment ( test_fn, NULL, - gcc_jit_context_new_field_access ( - ctxt, NULL, + gcc_jit_rvalue_dereference_field ( gcc_jit_param_as_rvalue (param_f), + NULL, "z"), sum); diff --git a/gcc/testsuite/jit.dg/test-combination.c b/gcc/testsuite/jit.dg/test-combination.c index 2bf7124..3338d94 100644 --- a/gcc/testsuite/jit.dg/test-combination.c +++ b/gcc/testsuite/jit.dg/test-combination.c @@ -28,6 +28,13 @@ #undef code_making_callback #undef verify_code +/* test-expressions.c */ +#define code_making_callback code_making_callback_expressions +#define verify_code verify_code_expressions +#include "test-expressions.c" +#undef code_making_callback +#undef verify_code + /* test-factorial.c */ #define code_making_callback code_making_callback_factorial #define verify_code verify_code_factorial @@ -95,6 +102,7 @@ code_making_callback (gcc_jit_context *ctxt, void * user_data) errors += code_making_callback_accessing_struct (ctxt, user_data); errors += code_making_callback_calling_external_function (ctxt, user_data); errors += code_making_callback_dot_product (ctxt, user_data); + errors += code_making_callback_expressions (ctxt, user_data); errors += code_making_callback_factorial (ctxt, user_data); errors += code_making_callback_fibonacci (ctxt, user_data); errors += code_making_callback_hello_world (ctxt, user_data); @@ -112,6 +120,7 @@ verify_code (gcc_jit_result *result) verify_code_accessing_struct (result); verify_code_calling_external_function (result); verify_code_dot_product (result); + verify_code_expressions (result); verify_code_factorial (result); verify_code_fibonacci (result); verify_code_hello_world (result); diff --git a/gcc/testsuite/jit.dg/test-expressions.c b/gcc/testsuite/jit.dg/test-expressions.c new file mode 100644 index 0000000..91103f8 --- /dev/null +++ b/gcc/testsuite/jit.dg/test-expressions.c @@ -0,0 +1,518 @@ +#include <stdlib.h> +#include <stdio.h> +#include <stddef.h> + +#include "libgccjit.h" + +#include "harness.h" + +/********************************************************************** + Unary ops + **********************************************************************/ + +static void +make_test_of_unary_op (gcc_jit_context *ctxt, + gcc_jit_type *type, + enum gcc_jit_unary_op op, + const char *funcname) +{ + /* Make a test function of the form: + T test_unary_op (T a) + { + return OP a; + } + */ + gcc_jit_param *param_a = + gcc_jit_context_new_param (ctxt, NULL, type, "a"); + gcc_jit_function *test_fn = + gcc_jit_context_new_function (ctxt, NULL, + GCC_JIT_FUNCTION_EXPORTED, + type, + funcname, + 1, ¶m_a, + 0); + gcc_jit_function_add_return ( + test_fn, + NULL, + gcc_jit_context_new_unary_op ( + ctxt, + NULL, + op, + type, + gcc_jit_param_as_rvalue (param_a))); +} + + +static void +make_tests_of_unary_ops (gcc_jit_context *ctxt) +{ + gcc_jit_type *int_type = + gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_INT); + + make_test_of_unary_op (ctxt, + int_type, + GCC_JIT_UNARY_OP_MINUS, + "test_UNARY_OP_MINUS_on_int"); + make_test_of_unary_op (ctxt, + int_type, + GCC_JIT_UNARY_OP_BITWISE_NEGATE, + "test_UNARY_OP_BITWISE_NEGATE_on_int"); + make_test_of_unary_op (ctxt, + int_type, + GCC_JIT_UNARY_OP_LOGICAL_NEGATE, + "test_UNARY_OP_LOGICAL_NEGATE_on_int"); +} + +static void +verify_unary_ops (gcc_jit_result *result) +{ + typedef int (*test_fn) (int); + + test_fn test_UNARY_OP_MINUS_on_int = + (test_fn)gcc_jit_result_get_code (result, + "test_UNARY_OP_MINUS_on_int"); + CHECK_NON_NULL (test_UNARY_OP_MINUS_on_int); + CHECK_VALUE (test_UNARY_OP_MINUS_on_int (0), 0); + CHECK_VALUE (test_UNARY_OP_MINUS_on_int (42), -42); + CHECK_VALUE (test_UNARY_OP_MINUS_on_int (-5), 5); + + test_fn test_UNARY_OP_BITWISE_NEGATE_on_int = + (test_fn)gcc_jit_result_get_code (result, + "test_UNARY_OP_BITWISE_NEGATE_on_int"); + CHECK_NON_NULL (test_UNARY_OP_BITWISE_NEGATE_on_int); + CHECK_VALUE (test_UNARY_OP_BITWISE_NEGATE_on_int (0), ~0); + CHECK_VALUE (test_UNARY_OP_BITWISE_NEGATE_on_int (42), ~42); + CHECK_VALUE (test_UNARY_OP_BITWISE_NEGATE_on_int (-5), ~-5); + + test_fn test_UNARY_OP_LOGICAL_NEGATE_on_int = + (test_fn)gcc_jit_result_get_code (result, + "test_UNARY_OP_LOGICAL_NEGATE_on_int"); + CHECK_NON_NULL (test_UNARY_OP_LOGICAL_NEGATE_on_int); + CHECK_VALUE (test_UNARY_OP_LOGICAL_NEGATE_on_int (0), 1); + CHECK_VALUE (test_UNARY_OP_LOGICAL_NEGATE_on_int (42), 0); + CHECK_VALUE (test_UNARY_OP_LOGICAL_NEGATE_on_int (-5), 0); + +} + +/********************************************************************** + Binary ops + **********************************************************************/ + +static void +make_test_of_binary_op (gcc_jit_context *ctxt, + gcc_jit_type *type, + enum gcc_jit_binary_op op, + const char *funcname) +{ + /* Make a test function of the form: + T test_binary_op (T a, T b) + { + return a OP b; + } + */ + gcc_jit_param *param_a = + gcc_jit_context_new_param (ctxt, NULL, type, "a"); + gcc_jit_param *param_b = + gcc_jit_context_new_param (ctxt, NULL, type, "b"); + gcc_jit_param *params[] = {param_a, param_b}; + gcc_jit_function *test_fn = + gcc_jit_context_new_function (ctxt, NULL, + GCC_JIT_FUNCTION_EXPORTED, + type, + funcname, + 2, params, + 0); + gcc_jit_function_add_return ( + test_fn, + NULL, + gcc_jit_context_new_binary_op ( + ctxt, + NULL, + op, + type, + gcc_jit_param_as_rvalue (param_a), + gcc_jit_param_as_rvalue (param_b))); +} + + +static void +make_tests_of_binary_ops (gcc_jit_context *ctxt) +{ + gcc_jit_type *int_type = + gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_INT); + + /* Test binary ops. */ + make_test_of_binary_op (ctxt, + int_type, + GCC_JIT_BINARY_OP_PLUS, + "test_BINARY_OP_PLUS_on_int"); + make_test_of_binary_op (ctxt, + int_type, + GCC_JIT_BINARY_OP_MINUS, + "test_BINARY_OP_MINUS_on_int"); + make_test_of_binary_op (ctxt, + int_type, + GCC_JIT_BINARY_OP_MULT, + "test_BINARY_OP_MULT_on_int"); + make_test_of_binary_op (ctxt, + int_type, + GCC_JIT_BINARY_OP_DIVIDE, + "test_BINARY_OP_DIVIDE_on_int"); + make_test_of_binary_op (ctxt, + int_type, + GCC_JIT_BINARY_OP_MODULO, + "test_BINARY_OP_MODULO_on_int"); + make_test_of_binary_op (ctxt, + int_type, + GCC_JIT_BINARY_OP_BITWISE_AND, + "test_BINARY_OP_BITWISE_AND_on_int"); + make_test_of_binary_op (ctxt, + int_type, + GCC_JIT_BINARY_OP_BITWISE_XOR, + "test_BINARY_OP_BITWISE_XOR_on_int"); + make_test_of_binary_op (ctxt, + int_type, + GCC_JIT_BINARY_OP_BITWISE_OR, + "test_BINARY_OP_BITWISE_OR_on_int"); + make_test_of_binary_op (ctxt, + int_type, + GCC_JIT_BINARY_OP_LOGICAL_AND, + "test_BINARY_OP_LOGICAL_AND_on_int"); + make_test_of_binary_op (ctxt, + int_type, + GCC_JIT_BINARY_OP_LOGICAL_OR, + "test_BINARY_OP_LOGICAL_OR_on_int"); +} + +static void +verify_binary_ops (gcc_jit_result *result) +{ + typedef int (*test_fn) (int, int); + + test_fn test_BINARY_OP_PLUS_on_int = + (test_fn)gcc_jit_result_get_code (result, + "test_BINARY_OP_PLUS_on_int"); + CHECK_NON_NULL (test_BINARY_OP_PLUS_on_int); + CHECK_VALUE (test_BINARY_OP_PLUS_on_int (0, 0), 0); + CHECK_VALUE (test_BINARY_OP_PLUS_on_int (1, 2), 3); + CHECK_VALUE (test_BINARY_OP_PLUS_on_int (100, -1), 99); + CHECK_VALUE (test_BINARY_OP_PLUS_on_int (-1, -4), -5); + + test_fn test_BINARY_OP_MINUS_on_int = + (test_fn)gcc_jit_result_get_code (result, + "test_BINARY_OP_MINUS_on_int"); + CHECK_NON_NULL (test_BINARY_OP_MINUS_on_int); + CHECK_VALUE (test_BINARY_OP_MINUS_on_int (0, 0), 0); + CHECK_VALUE (test_BINARY_OP_MINUS_on_int (1, 2), -1); + CHECK_VALUE (test_BINARY_OP_MINUS_on_int (100, -1), 101); + CHECK_VALUE (test_BINARY_OP_MINUS_on_int (-1, -4), 3); + + test_fn test_BINARY_OP_MULT_on_int = + (test_fn)gcc_jit_result_get_code (result, + "test_BINARY_OP_MULT_on_int"); + CHECK_NON_NULL (test_BINARY_OP_MULT_on_int); + CHECK_VALUE (test_BINARY_OP_MULT_on_int (0, 0), 0); + CHECK_VALUE (test_BINARY_OP_MULT_on_int (1, 2), 2); + CHECK_VALUE (test_BINARY_OP_MULT_on_int (100, -1), -100); + CHECK_VALUE (test_BINARY_OP_MULT_on_int (-1, -4), 4); + CHECK_VALUE (test_BINARY_OP_MULT_on_int (7, 10), 70); + + test_fn test_BINARY_OP_DIVIDE_on_int = + (test_fn)gcc_jit_result_get_code (result, + "test_BINARY_OP_DIVIDE_on_int"); + CHECK_NON_NULL (test_BINARY_OP_DIVIDE_on_int); + CHECK_VALUE (test_BINARY_OP_DIVIDE_on_int (7, 2), 3); + CHECK_VALUE (test_BINARY_OP_DIVIDE_on_int (100, -1), (100 / -1)); + CHECK_VALUE (test_BINARY_OP_DIVIDE_on_int (-1, -4), (-1 / -4)); + CHECK_VALUE (test_BINARY_OP_DIVIDE_on_int (60, 5), 12); + + test_fn test_BINARY_OP_MODULO_on_int = + (test_fn)gcc_jit_result_get_code (result, + "test_BINARY_OP_MODULO_on_int"); + CHECK_NON_NULL (test_BINARY_OP_MODULO_on_int); + CHECK_VALUE (test_BINARY_OP_MODULO_on_int (7, 2), 1); + CHECK_VALUE (test_BINARY_OP_MODULO_on_int (100, -1), (100 % -1)); + CHECK_VALUE (test_BINARY_OP_MODULO_on_int (-1, -4), (-1 % -4)); + CHECK_VALUE (test_BINARY_OP_MODULO_on_int (60, 5), 0); + + test_fn test_BINARY_OP_BITWISE_AND_on_int = + (test_fn)gcc_jit_result_get_code (result, + "test_BINARY_OP_BITWISE_AND_on_int"); + CHECK_NON_NULL (test_BINARY_OP_BITWISE_AND_on_int); + CHECK_VALUE (test_BINARY_OP_BITWISE_AND_on_int (0xf0f0, 0x7777), 0x7070); + + test_fn test_BINARY_OP_BITWISE_XOR_on_int = + (test_fn)gcc_jit_result_get_code (result, + "test_BINARY_OP_BITWISE_XOR_on_int"); + CHECK_NON_NULL (test_BINARY_OP_BITWISE_XOR_on_int); + CHECK_VALUE (test_BINARY_OP_BITWISE_XOR_on_int (0xf0f0, 0x7777), 0x8787); + + test_fn test_BINARY_OP_BITWISE_OR_on_int = + (test_fn)gcc_jit_result_get_code (result, + "test_BINARY_OP_BITWISE_OR_on_int"); + CHECK_NON_NULL (test_BINARY_OP_BITWISE_OR_on_int); + CHECK_VALUE (test_BINARY_OP_BITWISE_OR_on_int (0xf0f0, 0x7777), 0xf7f7); + + test_fn test_BINARY_OP_LOGICAL_AND_on_int = + (test_fn)gcc_jit_result_get_code (result, + "test_BINARY_OP_LOGICAL_AND_on_int"); + CHECK_NON_NULL (test_BINARY_OP_LOGICAL_AND_on_int); + CHECK_VALUE (test_BINARY_OP_LOGICAL_AND_on_int (0, 0), 0); + CHECK_VALUE (test_BINARY_OP_LOGICAL_AND_on_int (42, 0), 0); + CHECK_VALUE (test_BINARY_OP_LOGICAL_AND_on_int (0, -13), 0); + CHECK_VALUE (test_BINARY_OP_LOGICAL_AND_on_int (1997, 1998), 1); + + test_fn test_BINARY_OP_LOGICAL_OR_on_int = + (test_fn)gcc_jit_result_get_code (result, + "test_BINARY_OP_LOGICAL_OR_on_int"); + CHECK_NON_NULL (test_BINARY_OP_LOGICAL_OR_on_int); + CHECK_VALUE (test_BINARY_OP_LOGICAL_OR_on_int (0, 0), 0); + CHECK_VALUE (test_BINARY_OP_LOGICAL_OR_on_int (42, 0), 1); + CHECK_VALUE (test_BINARY_OP_LOGICAL_OR_on_int (0, -13), 1); + CHECK_VALUE (test_BINARY_OP_LOGICAL_OR_on_int (1997, 1998), 1); +} + +/********************************************************************** + Comparisons + **********************************************************************/ + +static void +make_test_of_comparison (gcc_jit_context *ctxt, + gcc_jit_type *type, + enum gcc_jit_comparison op, + const char *funcname) +{ + /* Make a test function of the form: + T test_comparison_op (T a, T b) + { + return a OP b; + } + */ + gcc_jit_param *param_a = + gcc_jit_context_new_param (ctxt, NULL, type, "a"); + gcc_jit_param *param_b = + gcc_jit_context_new_param (ctxt, NULL, type, "b"); + gcc_jit_param *params[] = {param_a, param_b}; + gcc_jit_function *test_fn = + gcc_jit_context_new_function (ctxt, NULL, + GCC_JIT_FUNCTION_EXPORTED, + type, + funcname, + 2, params, + 0); + gcc_jit_function_add_return ( + test_fn, + NULL, + gcc_jit_context_new_comparison ( + ctxt, + NULL, + op, + gcc_jit_param_as_rvalue (param_a), + gcc_jit_param_as_rvalue (param_b))); +} + +static void +make_tests_of_comparisons (gcc_jit_context *ctxt) +{ + gcc_jit_type *int_type = + gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_INT); + + make_test_of_comparison (ctxt, + int_type, + GCC_JIT_COMPARISON_EQ, + "test_COMPARISON_EQ_on_int"); + make_test_of_comparison (ctxt, + int_type, + GCC_JIT_COMPARISON_NE, + "test_COMPARISON_NE_on_int"); + make_test_of_comparison (ctxt, + int_type, + GCC_JIT_COMPARISON_LT, + "test_COMPARISON_LT_on_int"); + make_test_of_comparison (ctxt, + int_type, + GCC_JIT_COMPARISON_LE, + "test_COMPARISON_LE_on_int"); + make_test_of_comparison (ctxt, + int_type, + GCC_JIT_COMPARISON_GT, + "test_COMPARISON_GT_on_int"); + make_test_of_comparison (ctxt, + int_type, + GCC_JIT_COMPARISON_GE, + "test_COMPARISON_GE_on_int"); +} + +static void +verify_comparisons (gcc_jit_result *result) +{ + typedef int (*test_fn) (int, int); + + test_fn test_COMPARISON_EQ_on_int = + (test_fn)gcc_jit_result_get_code (result, + "test_COMPARISON_EQ_on_int"); + CHECK_NON_NULL (test_COMPARISON_EQ_on_int); + CHECK_VALUE (test_COMPARISON_EQ_on_int (0, 0), 1); + CHECK_VALUE (test_COMPARISON_EQ_on_int (1, 2), 0); + + test_fn test_COMPARISON_NE_on_int = + (test_fn)gcc_jit_result_get_code (result, + "test_COMPARISON_NE_on_int"); + CHECK_NON_NULL (test_COMPARISON_NE_on_int); + CHECK_VALUE (test_COMPARISON_NE_on_int (0, 0), 0); + CHECK_VALUE (test_COMPARISON_NE_on_int (1, 2), 1); + + test_fn test_COMPARISON_LT_on_int = + (test_fn)gcc_jit_result_get_code (result, + "test_COMPARISON_LT_on_int"); + CHECK_NON_NULL (test_COMPARISON_LT_on_int); + CHECK_VALUE (test_COMPARISON_LT_on_int (0, 0), 0); + CHECK_VALUE (test_COMPARISON_LT_on_int (1, 2), 1); + CHECK_VALUE (test_COMPARISON_LT_on_int (2, 1), 0); + CHECK_VALUE (test_COMPARISON_LT_on_int (-2, 1), 1); + + test_fn test_COMPARISON_LE_on_int = + (test_fn)gcc_jit_result_get_code (result, + "test_COMPARISON_LE_on_int"); + CHECK_NON_NULL (test_COMPARISON_LE_on_int); + CHECK_VALUE (test_COMPARISON_LE_on_int (0, 0), 1); + CHECK_VALUE (test_COMPARISON_LE_on_int (1, 2), 1); + CHECK_VALUE (test_COMPARISON_LE_on_int (2, 1), 0); + + test_fn test_COMPARISON_GT_on_int = + (test_fn)gcc_jit_result_get_code (result, + "test_COMPARISON_GT_on_int"); + CHECK_NON_NULL (test_COMPARISON_GT_on_int); + CHECK_VALUE (test_COMPARISON_GT_on_int (0, 0), 0); + CHECK_VALUE (test_COMPARISON_GT_on_int (1, 2), 0); + CHECK_VALUE (test_COMPARISON_GT_on_int (2, 1), 1); + + test_fn test_COMPARISON_GE_on_int = + (test_fn)gcc_jit_result_get_code (result, + "test_COMPARISON_GE_on_int"); + CHECK_NON_NULL (test_COMPARISON_GE_on_int); + CHECK_VALUE (test_COMPARISON_GE_on_int (0, 0), 1); + CHECK_VALUE (test_COMPARISON_GE_on_int (1, 2), 0); + CHECK_VALUE (test_COMPARISON_GE_on_int (2, 1), 1); +} + +/********************************************************************** + Dereferences + **********************************************************************/ + +static void +make_tests_of_dereferences (gcc_jit_context *ctxt) +{ + /* + int test_dereference_read (int *ptr) + { + return *ptr; + } + void test_dereference_write (int *ptr, int i) + { + *ptr = i; + } + */ + gcc_jit_type *void_type = + gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_VOID); + gcc_jit_type *int_type = + gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_INT); + gcc_jit_type *int_ptr_type = + gcc_jit_type_get_pointer (int_type); + { + gcc_jit_param *param_ptr = + gcc_jit_context_new_param (ctxt, NULL, int_ptr_type, "ptr"); + gcc_jit_function *test_dereference_read = + gcc_jit_context_new_function (ctxt, NULL, + GCC_JIT_FUNCTION_EXPORTED, + int_type, + "test_dereference_read", + 1, ¶m_ptr, + 0); + gcc_jit_function_add_return ( + test_dereference_read, + NULL, + gcc_jit_lvalue_as_rvalue ( + gcc_jit_rvalue_dereference ( + gcc_jit_param_as_rvalue (param_ptr), + NULL))); + } + + { + gcc_jit_param *param_ptr = + gcc_jit_context_new_param (ctxt, NULL, int_ptr_type, "ptr"); + gcc_jit_param *param_i = + gcc_jit_context_new_param (ctxt, NULL, int_type, "i"); + gcc_jit_param *params[] = {param_ptr, param_i}; + gcc_jit_function *test_dereference_write = + gcc_jit_context_new_function (ctxt, NULL, + GCC_JIT_FUNCTION_EXPORTED, + void_type, + "test_dereference_write", + 2, params, + 0); + gcc_jit_function_add_assignment ( + test_dereference_write, + NULL, + gcc_jit_rvalue_dereference ( + gcc_jit_param_as_rvalue (param_ptr), + NULL), + gcc_jit_param_as_rvalue (param_i)); + } +} + +static void +verify_dereferences (gcc_jit_result *result) +{ + int a = 42; + int b = -99; + + { + typedef int (*test_read) (int *); + test_read test_dereference_read = + (test_read)gcc_jit_result_get_code (result, + "test_dereference_read"); + CHECK_NON_NULL (test_dereference_read); + CHECK_VALUE (test_dereference_read (&a), 42); + CHECK_VALUE (test_dereference_read (&b), -99); + } + + { + typedef void (*test_write) (int *, int); + test_write test_dereference_write = + (test_write)gcc_jit_result_get_code (result, + "test_dereference_write"); + CHECK_NON_NULL (test_dereference_write); + test_dereference_write (&a, -55); + CHECK_VALUE (a, -55); + + test_dereference_write (&b, 404); + CHECK_VALUE (b, 404); + } +} + +/********************************************************************** + Code for harness + **********************************************************************/ + +int +code_making_callback (gcc_jit_context *ctxt, void *user_data) +{ + make_tests_of_unary_ops (ctxt); + make_tests_of_binary_ops (ctxt); + make_tests_of_comparisons (ctxt); + make_tests_of_dereferences (ctxt); + + return 0; +} + +void +verify_code (gcc_jit_result *result) +{ + CHECK_NON_NULL (result); + + verify_unary_ops (result); + verify_binary_ops (result); + verify_comparisons (result); + verify_dereferences (result); +} diff --git a/gcc/testsuite/jit.dg/test-types.c b/gcc/testsuite/jit.dg/test-types.c index 4c30547..819c40a 100644 --- a/gcc/testsuite/jit.dg/test-types.c +++ b/gcc/testsuite/jit.dg/test-types.c @@ -128,9 +128,9 @@ code_making_callback (gcc_jit_context *ctxt, void *user_data) #define ASSIGN(FIELDNAME, EXPR) \ gcc_jit_function_add_assignment ( \ test_fn, NULL, \ - gcc_jit_context_new_field_access ( \ - ctxt, NULL, \ + gcc_jit_rvalue_dereference_field ( \ gcc_jit_param_as_rvalue (param_z), \ + NULL, \ (FIELDNAME)), \ (EXPR)); -- 1.7.11.7