@@ -1,5 +1,75 @@
2013-10-18 David Malcolm <dmalcolm@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 <dmalcolm@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.
@@ -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
@@ -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 *
@@ -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)
{}
};
@@ -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 *
@@ -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,
@@ -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;
@@ -1,5 +1,13 @@
2013-10-18 David Malcolm <dmalcolm@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 <dmalcolm@redhat.com>
+
* jit.dg/test-null-passed-to-api.c: New.
2013-10-17 David Malcolm <dmalcolm@redhat.com>
@@ -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);
@@ -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);
new file mode 100644
@@ -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);
+}
@@ -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));