diff mbox

[jit] Improvements to array access (API change and additions)

Message ID 1391530631-21093-1-git-send-email-dmalcolm@redhat.com
State New
Headers show

Commit Message

David Malcolm Feb. 4, 2014, 4:17 p.m. UTC
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 mbox

Patch

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 (