Committed to branch dmalcolm/jit:

The following commit adds a way to create an array type from an existing
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);

and renames the array access API from:
        gcc_jit_context_new_array_lookup
to:
        gcc_jit_context_new_array_access
changing it to return an lvalue rather than an rvalue.

It also adds a helper function:

  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);

for creating loops of this form more easily:
        for (i = start_of_range; i < upper_bound_of_range; i += step)
        {
           BODY;
        }

 "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.

gcc/jit/
        * libgccjit.h (gcc_jit_context_new_array_type): New.
        (gcc_jit_context_new_array_lookup): Rename to...
        (gcc_jit_context_new_array_access): ...this, and change return
        type from rvalue to lvalue.
        (gcc_jit_function_new_loop_over_range): New.

        * libgccjit.map (gcc_jit_context_new_array_lookup): Rename to...
        (gcc_jit_context_new_array_access): ..this.
        (gcc_jit_context_new_array_type): New.
        (gcc_jit_function_new_loop_over_range): New.

        * libgccjit++.h (gccjit::context::new_array_type): New methods.
        (gccjit::context::new_array_access): New methods.

        * libgccjit.c (gcc_jit_context_new_array_type): New.
        (gcc_jit_context_new_array_lookup): Rename to...
        (gcc_jit_context_new_array_access): ...this, and change return
        type from rvalue to lvalue.
        (gcc_jit_function_new_loop): Provide NULL for the added arguments
        for the underlying API.
        (gcc_jit_function_new_loop_over_range): New.

        * internal-api.h (gcc::jit::recording::context::
        new_array_type): New.
        (gcc::jit::recording::context::new_array_lookup): Rename to...
        (gcc::jit::recording::context::new_array_access): ...this, and
        change return type from an rvalue to an lvalue.
        (gcc::jit::recording::array_type): New subclass of type.
        (gcc::jit::recording::function::new_loop): Add iteration_var and
        step params, so that we can add a += when the loop ends.
        (gcc::jit::recording::array_lookup): Rename to...
        (gcc::jit::recording::array_access): ...this, and subclass from
        lvalue rathern than rvalue.
        (gcc::jit::recording::loop): Add optional iteration_var and
        step fields, for use by gcc_jit_function_new_loop_over_range so
        that, if present, we can add a += when the loop ends.

        (gcc::jit::playback::context::new_array_type): New.
        (gcc::jit::playback::context::new_array_lookup): Rename to...
        (gcc::jit::playback::context::new_array_access): ...this, and
        change return type from an rvalue to an lvalue.

        * internal-api.c (gcc::jit::recording::context::new_array_type): New.
        (gcc::jit::recording::context::new_array_lookup): Rename to...
        (gcc::jit::recording::context::new_array_access): ...this, and
        change return type from an rvalue to an lvalue.
        (gcc::jit::recording::array_type::dereference): New.
        (gcc::jit::recording::array_type::replay_into): New.
        (gcc::jit::recording::array_type::make_debug_string): New.
        (gcc::jit::recording::function::new_loop): Add iteration_var and
        step params.
        (gcc::jit::recording::array_lookup): Rename to...
        (gcc::jit::recording::array_access): ...this.
        (gcc::jit::recording::loop::end): If we have an iteration_var, and
        thus a step, inject a += operation immediately before the loop
        end.
        (gcc::jit::playback::context::new_array_type): New.
        (gcc::jit::playback::context::new_array_lookup): Rename to...
        (gcc::jit::playback::context::new_array_access): ...this, and
        change return type from an rvalue to an lvalue.

gcc/testsuite/
        * jit.dg/test-arrays.c: New test case, verifying that array types
        work as expected (and using the the new
        gcc_jit_function_new_loop_over_range API call).

        * jit.dg/test-dot-product.c (create_code): Update for API changes to
        array access.
---
 gcc/jit/internal-api.c                  |  90 +++++++++++++++++---
 gcc/jit/internal-api.h                  |  72 +++++++++++++---
 gcc/jit/libgccjit++.h                   |  43 ++++++++++
 gcc/jit/libgccjit.c                     |  62 +++++++++++++-
 gcc/jit/libgccjit.h                     |  33 +++++++-
 gcc/jit/libgccjit.map                   |   4 +-
 gcc/testsuite/jit.dg/test-arrays.c      | 144 ++++++++++++++++++++++++++++++++
 gcc/testsuite/jit.dg/test-dot-product.c |  21 +++--
 8 files changed, 430 insertions(+), 39 deletions(-)
 create mode 100644 gcc/testsuite/jit.dg/test-arrays.c

diff --git a/gcc/jit/internal-api.c b/gcc/jit/internal-api.c
index e061ebd..85d8fd1 100644
--- a/gcc/jit/internal-api.c
+++ b/gcc/jit/internal-api.c
@@ -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);
     }
 }
 
diff --git a/gcc/jit/internal-api.h b/gcc/jit/internal-api.h
index ce46433..aa98728 100644
--- a/gcc/jit/internal-api.h
+++ b/gcc/jit/internal-api.h
@@ -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);
 
diff --git a/gcc/jit/libgccjit++.h b/gcc/jit/libgccjit++.h
index be2f9ed..79abcd1 100644
--- a/gcc/jit/libgccjit++.h
+++ b/gcc/jit/libgccjit++.h
@@ -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
diff --git a/gcc/jit/libgccjit.c b/gcc/jit/libgccjit.c
index 67d09ea..181954d 100644
--- a/gcc/jit/libgccjit.c
+++ b/gcc/jit/libgccjit.c
@@ -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 *
diff --git a/gcc/jit/libgccjit.h b/gcc/jit/libgccjit.h
index f408baf..1ef55d0 100644
--- a/gcc/jit/libgccjit.h
+++ b/gcc/jit/libgccjit.h
@@ -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);
diff --git a/gcc/jit/libgccjit.map b/gcc/jit/libgccjit.map
index 88cec7b..cbf9b33 100644
--- a/gcc/jit/libgccjit.map
+++ b/gcc/jit/libgccjit.map
@@ -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;
diff --git a/gcc/testsuite/jit.dg/test-arrays.c 
b/gcc/testsuite/jit.dg/test-arrays.c
new file mode 100644
index 0000000..2cff561
--- /dev/null
+++ b/gcc/testsuite/jit.dg/test-arrays.c
@@ -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, &param_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);
+
+}
diff --git a/gcc/testsuite/jit.dg/test-dot-product.c 
b/gcc/testsuite/jit.dg/test-dot-product.c
index 0cc6282..e78546c 100644
--- a/gcc/testsuite/jit.dg/test-dot-product.c
+++ b/gcc/testsuite/jit.dg/test-dot-product.c
@@ -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 (
-- 
1.7.11.7

Reply via email to