@@ -214,6 +214,17 @@ recording::context::get_type (enum gcc_jit_types kind)
return m_basic_types[kind];
}
+recording::type *
+recording::context::new_array_type (recording::location *loc,
+ recording::type *element_type,
+ int num_elements)
+{
+ recording::type *result =
+ new recording::array_type (this, loc, element_type, num_elements);
+ record (result);
+ return result;
+}
+
recording::field *
recording::context::new_field (recording::location *loc,
recording::type *type,
@@ -366,12 +377,12 @@ recording::context::new_call (recording::location *loc,
return result;
}
-recording::rvalue *
-recording::context::new_array_lookup (recording::location *loc,
+recording::lvalue *
+recording::context::new_array_access (recording::location *loc,
recording::rvalue *ptr,
recording::rvalue *index)
{
- recording::rvalue *result = new array_lookup (this, loc, ptr, index);
+ recording::lvalue *result = new array_access (this, loc, ptr, index);
record (result);
return result;
}
@@ -717,6 +728,31 @@ recording::memento_of_get_const::make_debug_string ()
"const %s", m_other_type->get_debug_string ());
}
+/* gcc::jit::recording::array_type */
+
+recording::type *
+recording::array_type::dereference ()
+{
+ return m_element_type;
+}
+
+void
+recording::array_type::replay_into (replayer *r)
+{
+ set_playback_obj (r->new_array_type (playback_location (m_loc),
+ m_element_type->playback_type (),
+ m_num_elements));
+}
+
+recording::string *
+recording::array_type::make_debug_string ()
+{
+ return string::from_printf (m_ctxt,
+ "%s[%d]",
+ m_element_type->get_debug_string (),
+ m_num_elements);
+}
+
/* gcc::jit::recording::field:: */
void
recording::field::replay_into (replayer *r)
@@ -979,9 +1015,12 @@ recording::function::add_return (recording::location *loc,
recording::loop *
recording::function::new_loop (recording::location *loc,
- recording::rvalue *boolval)
+ recording::rvalue *boolval,
+ recording::lvalue *iteration_var,
+ recording::rvalue *step)
{
- recording::loop *result = new recording::loop (this, loc, boolval);
+ recording::loop *result = new recording::loop (this, loc, boolval,
+ iteration_var, step);
m_ctxt->record (result);
return result;
}
@@ -1250,16 +1289,16 @@ recording::call::make_debug_string ()
}
void
-recording::array_lookup::replay_into (replayer *r)
+recording::array_access::replay_into (replayer *r)
{
set_playback_obj (
- r->new_array_lookup (playback_location (m_loc),
+ r->new_array_access (playback_location (m_loc),
m_ptr->playback_rvalue (),
m_index->playback_rvalue ()));
}
recording::string *
-recording::array_lookup::make_debug_string ()
+recording::array_access::make_debug_string ()
{
return string::from_printf (m_ctxt,
"%s[%s]",
@@ -1553,6 +1592,15 @@ recording::loop::make_debug_string ()
void
recording::loop::end (location *loc)
{
+ if (m_iteration_var)
+ m_func->add_assignment (
+ loc,
+ m_iteration_var,
+ m_ctxt->new_binary_op (loc,
+ GCC_JIT_BINARY_OP_PLUS,
+ m_iteration_var->get_type (),
+ m_iteration_var,
+ m_step));
recording::loop_end *m = new loop_end (this, loc);
m_ctxt->record (m);
}
@@ -1697,6 +1745,24 @@ get_type (enum gcc_jit_types type_)
return new type (type_node);
}
+playback::type *
+playback::context::
+new_array_type (playback::location *loc,
+ playback::type *element_type,
+ int num_elements)
+{
+ gcc_assert (element_type);
+
+ tree t = build_array_type_nelts (element_type->as_tree (),
+ num_elements);
+ layout_type (t);
+
+ if (loc)
+ set_tree_location (t, loc);
+
+ return new type (t);
+}
+
playback::field *
playback::context::
new_field (location *loc,
@@ -2166,9 +2232,9 @@ new_call (location *loc,
*/
}
-playback::rvalue *
+playback::lvalue *
playback::context::
-new_array_lookup (location *loc,
+new_array_access (location *loc,
rvalue *ptr,
rvalue *index)
{
@@ -2190,7 +2256,7 @@ new_array_lookup (location *loc,
NULL_TREE, NULL_TREE);
if (loc)
set_tree_location (t_result, loc);
- return new rvalue (this, t_result);
+ return new lvalue (this, t_result);
}
else
{
@@ -2211,7 +2277,7 @@ new_array_lookup (location *loc,
set_tree_location (t_indirection, loc);
}
- return new rvalue (this, t_indirection);
+ return new lvalue (this, t_indirection);
}
}
@@ -142,6 +142,11 @@ public:
type *
get_type (enum gcc_jit_types type);
+ type *
+ new_array_type (location *loc,
+ type *element_type,
+ int num_elements);
+
field *
new_field (location *loc,
type *type,
@@ -210,8 +215,8 @@ public:
function *func,
int numargs, rvalue **args);
- rvalue *
- new_array_lookup (location *loc,
+ lvalue *
+ new_array_access (location *loc,
rvalue *ptr,
rvalue *index);
@@ -504,6 +509,31 @@ private:
type *m_other_type;
};
+class array_type : public type
+{
+ public:
+ array_type (context *ctxt,
+ location *loc,
+ type *element_type,
+ int num_elements)
+ : type (ctxt),
+ m_loc (loc),
+ m_element_type (element_type),
+ m_num_elements (num_elements)
+ {}
+
+ type *dereference ();
+ void replay_into (replayer *);
+
+ private:
+ string * make_debug_string ();
+
+ private:
+ location *m_loc;
+ type *m_element_type;
+ int m_num_elements;
+};
+
class field : public memento
{
public:
@@ -724,7 +754,8 @@ public:
loop *
new_loop (location *loc,
- rvalue *boolval);
+ rvalue *boolval,
+ lvalue *iteration_var, rvalue *step);
type *get_return_type () const { return m_return_type; }
string * get_name () const { return m_name; }
@@ -963,14 +994,14 @@ private:
vec<rvalue *> m_args;
};
-class array_lookup : public rvalue
+class array_access : public lvalue
{
public:
- array_lookup (context *ctxt,
+ array_access (context *ctxt,
location *loc,
rvalue *ptr,
rvalue *index)
- : rvalue (ctxt, loc, ptr->get_type ()->dereference ()),
+ : lvalue (ctxt, loc, ptr->get_type ()->dereference ()),
m_ptr (ptr),
m_index (index)
{}
@@ -1293,11 +1324,15 @@ class loop : public memento
public:
loop (function *func,
location *loc,
- rvalue *boolval)
+ rvalue *boolval,
+ lvalue *iteration_var, rvalue *step)
: memento (func->m_ctxt),
m_func (func),
m_loc (loc),
- m_boolval (boolval) {}
+ m_boolval (boolval),
+ m_iteration_var (iteration_var),
+ m_step (step)
+ {}
void replay_into (replayer *r);
@@ -1316,6 +1351,18 @@ private:
function *m_func;
location *m_loc;
rvalue *m_boolval;
+
+ /* The following fields are for handling
+ gcc_jit_function_new_loop_over_range and are NULL for other loops.
+
+ We preserve these from "_over_range" calls so that we can inject a
+ += assignment in the correct place immediately before the loop ends.
+ This is done within the recording::loop::end () method.
+ The corresponding playback::loop class has no special handling for
+ this, with the += operation having become a regular assignment by
+ that time. */
+ lvalue *m_iteration_var;
+ rvalue *m_step;
};
class loop_end : public memento
@@ -1379,6 +1426,11 @@ public:
type *
get_type (enum gcc_jit_types type);
+ type *
+ new_array_type (location *loc,
+ type *element_type,
+ int num_elements);
+
field *
new_field (location *loc,
type *type,
@@ -1444,8 +1496,8 @@ public:
function *func,
vec<rvalue *> args);
- rvalue *
- new_array_lookup (location *loc,
+ lvalue *
+ new_array_access (location *loc,
rvalue *ptr,
rvalue *index);
@@ -38,6 +38,9 @@ namespace gccjit
type get_type (enum gcc_jit_types kind);
+ type new_array_type (type element_type, int num_elements);
+ type new_array_type (location loc, type element_type, int num_elements);
+
field new_field (type type_, const char *name);
field new_field (location loc, type type_, const char *name);
@@ -103,6 +106,12 @@ namespace gccjit
function func,
std::vector<rvalue> args);
+ lvalue new_array_access (rvalue ptr,
+ rvalue index);
+ lvalue new_array_access (location loc,
+ rvalue ptr,
+ rvalue index);
+
public:
gcc_jit_context *m_inner_ctxt;
};
@@ -303,6 +312,22 @@ context::get_type (enum gcc_jit_types kind)
return type (gcc_jit_context_get_type (m_inner_ctxt, kind));
}
+inline type
+context::new_array_type (type element_type, int num_elements)
+{
+ return new_array_type (location (), element_type, num_elements);
+}
+
+inline type
+context::new_array_type (location loc, type element_type, int num_elements)
+{
+ return type (gcc_jit_context_new_array_type (
+ m_inner_ctxt,
+ loc.get_inner_location (),
+ element_type.get_inner_type (),
+ num_elements));
+}
+
inline field
context::new_field (type type_, const char *name)
{
@@ -550,6 +575,24 @@ context::new_call (location loc,
as_array_of_ptrs);
}
+inline lvalue
+context::new_array_access (rvalue ptr,
+ rvalue index)
+{
+ return new_array_access (location (), ptr, index);
+}
+
+inline lvalue
+context::new_array_access (location loc,
+ rvalue ptr,
+ rvalue index)
+{
+ return lvalue (gcc_jit_context_new_array_access (m_inner_ctxt,
+ loc.get_inner_location (),
+ ptr.get_inner_rvalue (),
+ index.get_inner_rvalue ()));
+}
+
// class object
inline std::string
object::get_debug_string () const
@@ -261,6 +261,20 @@ gcc_jit_type_get_const (gcc_jit_type *type)
return (gcc_jit_type *)type->get_const ();
}
+gcc_jit_type *
+gcc_jit_context_new_array_type (gcc_jit_context *ctxt,
+ gcc_jit_location *loc,
+ gcc_jit_type *element_type,
+ int num_elements)
+{
+ RETURN_NULL_IF_FAIL (ctxt, NULL, "NULL context");
+ RETURN_NULL_IF_FAIL (element_type, ctxt, "NULL type");
+
+ return (gcc_jit_type *)ctxt->new_array_type (loc,
+ element_type,
+ num_elements);
+}
+
gcc_jit_field *
gcc_jit_context_new_field (gcc_jit_context *ctxt,
gcc_jit_location *loc,
@@ -601,8 +615,8 @@ gcc_jit_context_new_call (gcc_jit_context *ctxt,
(gcc::jit::recording::rvalue **)args);
}
-extern gcc_jit_rvalue *
-gcc_jit_context_new_array_lookup (gcc_jit_context *ctxt,
+extern gcc_jit_lvalue *
+gcc_jit_context_new_array_access (gcc_jit_context *ctxt,
gcc_jit_location *loc,
gcc_jit_rvalue *ptr,
gcc_jit_rvalue *index)
@@ -611,7 +625,7 @@ gcc_jit_context_new_array_lookup (gcc_jit_context *ctxt,
RETURN_NULL_IF_FAIL (ptr, ctxt, "NULL ptr");
RETURN_NULL_IF_FAIL (index, ctxt, "NULL index");
- return (gcc_jit_rvalue *)ctxt->new_array_lookup (loc, ptr, index);
+ return (gcc_jit_lvalue *)ctxt->new_array_access (loc, ptr, index);
}
gcc_jit_context *
@@ -861,7 +875,47 @@ gcc_jit_function_new_loop (gcc_jit_function *func,
RETURN_NULL_IF_NOT_FUNC_DEFINITION (func);
RETURN_NULL_IF_FAIL (boolval, NULL, "NULL boolval");
- return (gcc_jit_loop *)func->new_loop (loc, boolval);
+ return (gcc_jit_loop *)func->new_loop (loc, boolval, NULL, NULL);
+}
+
+gcc_jit_loop *
+gcc_jit_function_new_loop_over_range (gcc_jit_function *func,
+ gcc_jit_location *loc,
+ gcc_jit_lvalue *iteration_var,
+ gcc_jit_rvalue *start_of_range,
+ gcc_jit_rvalue *upper_bound_of_range,
+ gcc_jit_rvalue *step)
+{
+ RETURN_NULL_IF_NOT_FUNC_DEFINITION (func);
+ gcc_jit_context *ctxt = static_cast <gcc_jit_context *> (func->m_ctxt);
+ RETURN_NULL_IF_FAIL (iteration_var, ctxt, "NULL iteration_var");
+ RETURN_NULL_IF_FAIL (upper_bound_of_range, ctxt,
+ "NULL upper_bound_of_range");
+ if (!start_of_range)
+ start_of_range =
+ gcc_jit_context_zero (ctxt,
+ static_cast <gcc_jit_type *> (iteration_var->get_type ()));
+
+ if (!step)
+ step = gcc_jit_context_one (ctxt,
+ static_cast <gcc_jit_type *> (iteration_var->get_type ()));
+
+ /* "iteration_var = start_of_range;" */
+ gcc_jit_function_add_assignment (func,
+ loc,
+ iteration_var,
+ start_of_range);
+
+ /* "(iteration_var < upper_bound_of_range)" */
+ gcc_jit_rvalue *boolval =
+ gcc_jit_context_new_comparison (ctxt,
+ loc,
+ GCC_JIT_COMPARISON_LT,
+ gcc_jit_lvalue_as_rvalue (iteration_var),
+ upper_bound_of_range);
+
+ /* the += is added when loop_end is called. */
+ return (gcc_jit_loop *)func->new_loop (loc, boolval, iteration_var, step);
}
gcc_jit_object *
@@ -359,6 +359,13 @@ gcc_jit_type_get_pointer (gcc_jit_type *type);
extern gcc_jit_type *
gcc_jit_type_get_const (gcc_jit_type *type);
+/* Given type "T", get type "T[N]" (for a constant N). */
+extern gcc_jit_type *
+gcc_jit_context_new_array_type (gcc_jit_context *ctxt,
+ gcc_jit_location *loc,
+ gcc_jit_type *element_type,
+ int num_elements);
+
/* Struct-handling. */
extern gcc_jit_field *
gcc_jit_context_new_field (gcc_jit_context *ctxt,
@@ -522,7 +529,7 @@ 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. */
+ For pointer addition, use gcc_jit_context_new_array_access. */
GCC_JIT_BINARY_OP_PLUS,
/* Subtraction of arithmetic values; analogous to:
@@ -617,8 +624,8 @@ gcc_jit_context_new_call (gcc_jit_context *ctxt,
gcc_jit_function *func,
int numargs , gcc_jit_rvalue **args);
-extern gcc_jit_rvalue *
-gcc_jit_context_new_array_lookup (gcc_jit_context *ctxt,
+extern gcc_jit_lvalue *
+gcc_jit_context_new_array_access (gcc_jit_context *ctxt,
gcc_jit_location *loc,
gcc_jit_rvalue *ptr,
gcc_jit_rvalue *index);
@@ -812,6 +819,26 @@ gcc_jit_function_new_loop (gcc_jit_function *func,
gcc_jit_location *loc,
gcc_jit_rvalue *boolval);
+/* Helper function for creating a loop of this form:
+ for (i = start_of_range; i < upper_bound_of_range; i += step)
+ {
+ BODY;
+ }
+
+ Statements will be added to the body of the loop until
+ gcc_jit_loop_end is called.
+
+ "start_of_range" can be NULL, in which case 0 is used.
+ "upper_bound_of_range" must be non-NULL.
+ "step" can be NULL, in which case 1 is used. */
+extern gcc_jit_loop *
+gcc_jit_function_new_loop_over_range (gcc_jit_function *func,
+ gcc_jit_location *loc,
+ gcc_jit_lvalue *iteration_var,
+ gcc_jit_rvalue *start_of_range,
+ gcc_jit_rvalue *upper_bound_of_range,
+ gcc_jit_rvalue *step);
+
/* Upcasting from loop to object. */
extern gcc_jit_object *
gcc_jit_loop_as_object (gcc_jit_loop *loop);
@@ -6,7 +6,8 @@
gcc_jit_context_compile;
gcc_jit_context_get_first_error;
gcc_jit_context_get_type;
- gcc_jit_context_new_array_lookup;
+ gcc_jit_context_new_array_access;
+ gcc_jit_context_new_array_type;
gcc_jit_context_new_binary_op;
gcc_jit_context_new_call;
gcc_jit_context_new_child_context;
@@ -41,6 +42,7 @@
gcc_jit_function_new_forward_label;
gcc_jit_function_new_local;
gcc_jit_function_new_loop;
+ gcc_jit_function_new_loop_over_range;
gcc_jit_function_place_forward_label;
gcc_jit_label_as_object;
gcc_jit_location_as_object;
new file mode 100644
@@ -0,0 +1,144 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <stddef.h>
+
+#include "libgccjit.h"
+
+#include "harness.h"
+
+#define ARRAY_SIZE (4)
+
+/* Verify that struct layout works properly when adding an array field. */
+struct array_holder
+{
+ float m_before;
+ int m_ints[ARRAY_SIZE];
+ float m_after;
+};
+
+void
+create_code (gcc_jit_context *ctxt, void *user_data)
+{
+ /* Let's try to inject the equivalent of:
+
+ void
+ test_array (struct array_holder *ah)
+ {
+ ah->m_before = 4.0f;
+ for i in 0 to (ARRAY_SIZE - 1):
+ ah->m_ints[i] = (i * i);
+ ah->m_after = 2.0f;
+ }
+ */
+ gcc_jit_type *void_type =
+ gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_VOID);
+ gcc_jit_type *float_type =
+ gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_FLOAT);
+ gcc_jit_type *int_type =
+ gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_INT);
+
+ gcc_jit_field *field_m_before =
+ gcc_jit_context_new_field (ctxt, NULL, float_type, "m_before");
+ gcc_jit_field *field_m_ints =
+ gcc_jit_context_new_field (
+ ctxt, NULL,
+ gcc_jit_context_new_array_type (ctxt, NULL, int_type, ARRAY_SIZE),
+ "m_ints");
+ gcc_jit_field *field_m_after =
+ gcc_jit_context_new_field (ctxt, NULL, float_type, "m_after");
+
+ gcc_jit_field *fields[] = {
+ field_m_before,
+ field_m_ints,
+ field_m_after,
+ };
+
+ gcc_jit_type *struct_type =
+ gcc_jit_context_new_struct_type (
+ ctxt,
+ NULL,
+ "array_holder",
+ 3, fields);
+
+ gcc_jit_type *struct_ptr_type =
+ gcc_jit_type_get_pointer (struct_type);
+
+ /* Build the test_fn. */
+ gcc_jit_param *param_ah =
+ gcc_jit_context_new_param (ctxt, NULL, struct_ptr_type, "ah");
+ gcc_jit_function *func =
+ gcc_jit_context_new_function (ctxt, NULL,
+ GCC_JIT_FUNCTION_EXPORTED,
+ void_type,
+ "test_array",
+ 1, ¶m_ah,
+ 0);
+
+ /* "ah->m_before = 4.0f;" */
+ gcc_jit_function_add_assignment (
+ func, NULL,
+ gcc_jit_rvalue_dereference_field (
+ gcc_jit_param_as_rvalue (param_ah), NULL, field_m_before),
+ gcc_jit_context_new_rvalue_from_int (ctxt, float_type, 4));
+
+ gcc_jit_function_add_comment (func, NULL,
+ "for i in 0 to (ARRAY_SIZE - 1):");
+ gcc_jit_lvalue *i =
+ gcc_jit_function_new_local (func, NULL, int_type, "i");
+ gcc_jit_loop *loop =
+ gcc_jit_function_new_loop_over_range (
+ func, NULL, i,
+ NULL,
+ gcc_jit_context_new_rvalue_from_int (ctxt, int_type, ARRAY_SIZE),
+ NULL);
+
+ gcc_jit_function_add_comment (func, NULL, "ah->m_ints[i] = (i * i);");
+ gcc_jit_function_add_assignment (
+ func, NULL,
+ gcc_jit_context_new_array_access (
+ ctxt, NULL,
+ gcc_jit_lvalue_as_rvalue (gcc_jit_rvalue_dereference_field (
+ gcc_jit_param_as_rvalue (param_ah),
+ NULL,
+ field_m_ints)),
+ gcc_jit_lvalue_as_rvalue (i)),
+ gcc_jit_context_new_binary_op (
+ ctxt, NULL,
+ GCC_JIT_BINARY_OP_MULT,
+ int_type,
+ gcc_jit_lvalue_as_rvalue (i),
+ gcc_jit_lvalue_as_rvalue (i)));
+
+ gcc_jit_loop_end (loop, NULL);
+
+ /* ah->m_after = 2.0f; */
+ gcc_jit_function_add_assignment (
+ func, NULL,
+ gcc_jit_rvalue_dereference_field (
+ gcc_jit_param_as_rvalue (param_ah), NULL, field_m_after),
+ gcc_jit_context_new_rvalue_from_int (ctxt, float_type, 2));
+
+}
+
+void
+verify_code (gcc_jit_context *ctxt, gcc_jit_result *result)
+{
+ typedef void (*fn_type) (struct array_holder *ah);
+
+ CHECK_NON_NULL (result);
+ fn_type test_array =
+ (fn_type)gcc_jit_result_get_code (result, "test_array");
+ CHECK_NON_NULL (test_array);
+
+ struct array_holder ah;
+ memset (&ah, 0xf0, sizeof (ah));
+
+ test_array (&ah);
+ CHECK_VALUE (ah.m_before, 4.0f);
+ CHECK_VALUE (ah.m_ints[0], 0);
+ CHECK_VALUE (ah.m_ints[1], 1);
+ CHECK_VALUE (ah.m_ints[2], 4);
+ CHECK_VALUE (ah.m_ints[3], 9);
+ CHECK_VALUE (ah.m_after, 2.0f);
+
+}
@@ -68,17 +68,20 @@ create_code (gcc_jit_context *ctxt, void *user_data)
func, NULL,
result,
GCC_JIT_BINARY_OP_PLUS,
- gcc_jit_context_new_binary_op (ctxt, NULL,
+ gcc_jit_context_new_binary_op (
+ ctxt, NULL,
GCC_JIT_BINARY_OP_MULT,
val_type,
- gcc_jit_context_new_array_lookup(
- ctxt, NULL,
- gcc_jit_param_as_rvalue (param_a),
- gcc_jit_lvalue_as_rvalue (i)),
- gcc_jit_context_new_array_lookup(
- ctxt, NULL,
- gcc_jit_param_as_rvalue (param_b),
- gcc_jit_lvalue_as_rvalue (i))));
+ gcc_jit_lvalue_as_rvalue (
+ gcc_jit_context_new_array_access (
+ ctxt, NULL,
+ gcc_jit_param_as_rvalue (param_a),
+ gcc_jit_lvalue_as_rvalue (i))),
+ gcc_jit_lvalue_as_rvalue (
+ gcc_jit_context_new_array_access (
+ ctxt, NULL,
+ gcc_jit_param_as_rvalue (param_b),
+ gcc_jit_lvalue_as_rvalue (i)))));
/* Build: "i++" */
gcc_jit_function_add_assignment_op (