[committed] jit: implement gcc_jit_context_new_rvalue_from_vector

David Malcolm dmalcolm@redhat.com
Wed Oct 4 13:45:00 GMT 2017


This patch implements a new API entrypoint:

/* Build a vector rvalue from an array of elements.

   "vec_type" should be a vector type, created using gcc_jit_type_get_vector.

   This API entrypoint was added in LIBGCCJIT_ABI_10; you can test for its
   presence using
     #ifdef LIBGCCJIT_HAVE_gcc_jit_context_new_rvalue_from_vector
*/
extern gcc_jit_rvalue *
gcc_jit_context_new_rvalue_from_vector (gcc_jit_context *ctxt,
                                        gcc_jit_location *loc,
                                        gcc_jit_type *vec_type,
                                        size_t num_elements,
                                        gcc_jit_rvalue **elements);

Successfully bootstrapped & regrtested on x86_64-pc-linux-gnu;
takes jit.sum from 9909 to 10294 PASS results.

Committed to trunk as r253409.

gcc/jit/ChangeLog:
	* docs/cp/topics/expressions.rst (Vector expressions): New
	section.
	* docs/topics/compatibility.rst (LIBGCCJIT_ABI_10): New ABI tag.
	* docs/topics/expressions.rst (Vector expressions): New section.
	* docs/topics/types.rst (gcc_jit_type_get_vector): Add link to
	gcc_jit_context_new_rvalue_from_vector.
	* jit-common.h (gcc::jit:recording::vector_type): New forward
	decl.
	* jit-playback.c
	(gcc::jit::playback::context::new_rvalue_from_vector): New method.
	* jit-playback.h
	(gcc::jit::playback::context::new_rvalue_from_vector): New method.
	* jit-recording.c: In namespace gcc::jit::
	(class comma_separated_string): New class.
	(comma_separated_string::comma_separated_string): New ctor,
	adapted from recording::call::make_debug_string.
	(comma_separated_string::~comma_separated_string): New dtor.
	In namespace gcc::jit::recording::
	(context::new_rvalue_from_vector): New method.
	(type::get_vector): Update for renaming of memento_of_get_vector.
	(class memento_of_get_vector): Rename to...
	(class vector_type): ..this.
	(memento_of_new_rvalue_from_vector::memento_of_new_rvalue_from_vector):
	New ctor.
	(memento_of_new_rvalue_from_vector::replay_into): New method.
	(memento_of_new_rvalue_from_vector::visit_children): New method.
	(memento_of_new_rvalue_from_vector::make_debug_string): New
	method.
	(memento_of_new_rvalue_from_vector::write_reproducer): New method.
	(call::make_debug_string): Split out arg-printing code into ctor
	for comma_separated_string.
	* jit-recording.h: In namespace gcc::jit::recording::
	(context::new_rvalue_from_vector): New method.
	(type::dyn_cast_vector_type): New virtual function.
	(class memento_of_get_vector): Rename to...
	(class vector_type): ...this.
	(vector_type::unqualified): Remove this vfunc override in favor
	of...
	(vector_type::get_element_type): ...this new method.
	(vector_type::get_num_units): New method.
	(vector_type::dyn_cast_vector_type): New vfunc override.
	(class memento_of_new_rvalue_from_vector): New class.
	* libgccjit++.h (gccjit::context::new_rvalue): Add overload for
	vector of rvalue.
	* libgccjit.c (gcc_jit_context_new_binary_op): Strip off type
	qualifications when checking that both operands have same type.
	(gcc_jit_context_new_rvalue_from_vector): New API entrypoint.
	* libgccjit.h
	(LIBGCCJIT_HAVE_gcc_jit_context_new_rvalue_from_vector): New
	macro.
	(gcc_jit_context_new_rvalue_from_vector): New API entrypoint.
	* libgccjit.map (LIBGCCJIT_ABI_10): New ABI tag.

gcc/testsuite/ChangeLog:
	* jit.dg/test-expressions.c (make_test_of_vectors): New function.
	(create_code): Call it.
	* jit.dg/test-vector-rvalues.cc: New test case.
---
 gcc/jit/docs/cp/topics/expressions.rst      |  11 ++
 gcc/jit/docs/topics/compatibility.rst       |   8 ++
 gcc/jit/docs/topics/expressions.rst         |  24 ++++
 gcc/jit/docs/topics/types.rst               |   3 +
 gcc/jit/jit-common.h                        |   1 +
 gcc/jit/jit-playback.c                      |  16 +++
 gcc/jit/jit-playback.h                      |   5 +
 gcc/jit/jit-recording.c                     | 207 ++++++++++++++++++++++-----
 gcc/jit/jit-recording.h                     |  42 +++++-
 gcc/jit/libgccjit++.h                       |  22 +++
 gcc/jit/libgccjit.c                         |  60 +++++++-
 gcc/jit/libgccjit.h                         |  17 +++
 gcc/jit/libgccjit.map                       |   5 +
 gcc/testsuite/jit.dg/test-expressions.c     |  30 ++++
 gcc/testsuite/jit.dg/test-vector-rvalues.cc | 211 ++++++++++++++++++++++++++++
 15 files changed, 622 insertions(+), 40 deletions(-)
 create mode 100644 gcc/testsuite/jit.dg/test-vector-rvalues.cc

diff --git a/gcc/jit/docs/cp/topics/expressions.rst b/gcc/jit/docs/cp/topics/expressions.rst
index 147d065..b0081f6 100644
--- a/gcc/jit/docs/cp/topics/expressions.rst
+++ b/gcc/jit/docs/cp/topics/expressions.rst
@@ -105,6 +105,17 @@ Simple expressions
    Generate an rvalue of type :c:data:`GCC_JIT_TYPE_CONST_CHAR_PTR` for
    the given string.  This is akin to a string literal.
 
+Vector expressions
+******************
+
+.. function:: gccjit::rvalue \
+	      gccjit::context::new_rvalue (gccjit::type vector_type, \
+	                                   std::vector<gccjit::rvalue> elements) const
+
+   Given a vector type, and a vector of scalar rvalue elements, generate a
+   vector rvalue.
+
+   The number of elements needs to match that of the vector type.
 
 Unary Operations
 ****************
diff --git a/gcc/jit/docs/topics/compatibility.rst b/gcc/jit/docs/topics/compatibility.rst
index 8408939..84d342b 100644
--- a/gcc/jit/docs/topics/compatibility.rst
+++ b/gcc/jit/docs/topics/compatibility.rst
@@ -163,3 +163,11 @@ entrypoints:
 -------------------
 ``LIBGCCJIT_ABI_9`` covers the addition of
 :func:`gcc_jit_function_get_address`
+
+.. _LIBGCCJIT_ABI_10:
+
+``LIBGCCJIT_ABI_10``
+--------------------
+
+``LIBGCCJIT_ABI_10`` covers the addition of
+:func:`gcc_jit_context_new_rvalue_from_vector`
diff --git a/gcc/jit/docs/topics/expressions.rst b/gcc/jit/docs/topics/expressions.rst
index 76aa4eb..e6e09dd 100644
--- a/gcc/jit/docs/topics/expressions.rst
+++ b/gcc/jit/docs/topics/expressions.rst
@@ -126,6 +126,30 @@ Simple expressions
    underlying string, so it is valid to pass in a pointer to an on-stack
    buffer.
 
+Vector expressions
+******************
+
+.. function:: gcc_jit_rvalue * \
+              gcc_jit_context_new_rvalue_from_vector (gcc_jit_context *ctxt, \
+                                                      gcc_jit_location *loc, \
+                                                      gcc_jit_type *vec_type, \
+                                                      size_t num_elements, \
+                                                      gcc_jit_rvalue **elements)
+
+   Build a vector rvalue from an array of elements.
+
+   "vec_type" should be a vector type, created using
+   :func:`gcc_jit_type_get_vector`.
+
+   "num_elements" should match that of the vector type.
+
+   This entrypoint was added in :ref:`LIBGCCJIT_ABI_10`; you can test for
+   its presence using
+
+   .. code-block:: c
+
+      #ifdef LIBGCCJIT_HAVE_gcc_jit_context_new_rvalue_from_vector
+
 Unary Operations
 ****************
 
diff --git a/gcc/jit/docs/topics/types.rst b/gcc/jit/docs/topics/types.rst
index 35a8231..a9ab9b3 100644
--- a/gcc/jit/docs/topics/types.rst
+++ b/gcc/jit/docs/topics/types.rst
@@ -177,6 +177,9 @@ Vector types
 
       #ifdef LIBGCCJIT_HAVE_gcc_jit_type_get_vector
 
+   Vector rvalues can be generated using
+   :func:`gcc_jit_context_new_rvalue_from_vector`.
+
 
 Structures and unions
 ---------------------
diff --git a/gcc/jit/jit-common.h b/gcc/jit/jit-common.h
index c931b3f..daf94a0 100644
--- a/gcc/jit/jit-common.h
+++ b/gcc/jit/jit-common.h
@@ -117,6 +117,7 @@ namespace recording {
       class compound_type;
         class struct_;
 	class union_;
+      class vector_type;
     class field;
     class fields;
     class function;
diff --git a/gcc/jit/jit-playback.c b/gcc/jit/jit-playback.c
index 5798179..95126c9 100644
--- a/gcc/jit/jit-playback.c
+++ b/gcc/jit/jit-playback.c
@@ -629,6 +629,22 @@ new_string_literal (const char *value)
   return new rvalue (this, t_addr);
 }
 
+/* Construct a playback::rvalue instance (wrapping a tree) for a
+   vector.  */
+
+playback::rvalue *
+playback::context::new_rvalue_from_vector (location *,
+					   type *type,
+					   const auto_vec<rvalue *> &elements)
+{
+  vec<constructor_elt, va_gc> *v;
+  vec_alloc (v, elements.length ());
+  for (unsigned i = 0; i < elements.length (); ++i)
+    CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, elements[i]->as_tree ());
+  tree t_ctor = build_constructor (type->as_tree (), v);
+  return new rvalue (this, t_ctor);
+}
+
 /* Coerce a tree expression into a boolean tree expression.  */
 
 tree
diff --git a/gcc/jit/jit-playback.h b/gcc/jit/jit-playback.h
index 746f5da..b45f6d5 100644
--- a/gcc/jit/jit-playback.h
+++ b/gcc/jit/jit-playback.h
@@ -114,6 +114,11 @@ public:
   new_string_literal (const char *value);
 
   rvalue *
+  new_rvalue_from_vector (location *loc,
+			  type *type,
+			  const auto_vec<rvalue *> &elements);
+
+  rvalue *
   new_unary_op (location *loc,
 		enum gcc_jit_unary_op op,
 		type *result_type,
diff --git a/gcc/jit/jit-recording.c b/gcc/jit/jit-recording.c
index 6d7dc80..bd8f116 100644
--- a/gcc/jit/jit-recording.c
+++ b/gcc/jit/jit-recording.c
@@ -447,6 +447,62 @@ reproducer::xstrdup_printf (const char *fmt, ...)
   return result;
 }
 
+/* A helper class for implementing make_debug_string, for building
+   a temporary string from a vec of rvalues.  */
+
+class comma_separated_string
+{
+ public:
+  comma_separated_string (const auto_vec<recording::rvalue *> &rvalues,
+			  enum recording::precedence prec);
+  ~comma_separated_string ();
+
+  const char *as_char_ptr () const { return m_buf; }
+
+ private:
+  char *m_buf;
+};
+
+/* comma_separated_string's ctor
+   Build m_buf.  */
+
+comma_separated_string::comma_separated_string
+  (const auto_vec<recording::rvalue *> &rvalues,
+   enum recording::precedence prec)
+: m_buf (NULL)
+{
+  /* Calculate length of said buffer.  */
+  size_t sz = 1; /* nil terminator */
+  for (unsigned i = 0; i< rvalues.length (); i++)
+    {
+      sz += strlen (rvalues[i]->get_debug_string_parens (prec));
+      sz += 2; /* ", " separator */
+    }
+
+  /* Now allocate and populate the buffer.  */
+  m_buf = new char[sz];
+  size_t len = 0;
+
+  for (unsigned i = 0; i< rvalues.length (); i++)
+    {
+      strcpy (m_buf + len, rvalues[i]->get_debug_string_parens (prec));
+      len += strlen (rvalues[i]->get_debug_string_parens (prec));
+      if (i + 1 < rvalues.length ())
+	{
+	  strcpy (m_buf + len, ", ");
+	  len += 2;
+	}
+    }
+  m_buf[len] = '\0';
+}
+
+/* comma_separated_string's dtor.  */
+
+comma_separated_string::~comma_separated_string ()
+{
+  delete[] m_buf;
+}
+
 /**********************************************************************
  Recording.
  **********************************************************************/
@@ -1001,6 +1057,23 @@ recording::context::new_string_literal (const char *value)
   return result;
 }
 
+/* Create a recording::memento_of_new_rvalue_from_vector instance and add it
+   to this context's list of mementos.
+
+   Implements the post-error-checking part of
+   gcc_jit_context_new_rvalue_from_vector.  */
+
+recording::rvalue *
+recording::context::new_rvalue_from_vector (location *loc,
+					    vector_type *type,
+					    rvalue **elements)
+{
+  recording::rvalue *result
+    = new memento_of_new_rvalue_from_vector (this, loc, type, elements);
+  record (result);
+  return result;
+}
+
 /* Create a recording::unary_op instance and add it to this context's
    list of mementos.
 
@@ -2035,7 +2108,7 @@ recording::type *
 recording::type::get_vector (size_t num_units)
 {
   recording::type *result
-    = new memento_of_get_vector (this, num_units);
+    = new vector_type (this, num_units);
   m_ctxt->record (result);
   return result;
 }
@@ -2523,13 +2596,13 @@ recording::memento_of_get_aligned::write_reproducer (reproducer &r)
 	   m_alignment_in_bytes);
 }
 
-/* The implementation of class gcc::jit::recording::memento_of_get_vector.  */
+/* The implementation of class gcc::jit::recording::vector_type.  */
 
 /* Implementation of pure virtual hook recording::memento::replay_into
-   for recording::memento_of_get_vector.  */
+   for recording::vector_type.  */
 
 void
-recording::memento_of_get_vector::replay_into (replayer *)
+recording::vector_type::replay_into (replayer *)
 {
   set_playback_obj
     (m_other_type->playback_type ()->get_vector (m_num_units));
@@ -2539,7 +2612,7 @@ recording::memento_of_get_vector::replay_into (replayer *)
    results of get_vector.  */
 
 recording::string *
-recording::memento_of_get_vector::make_debug_string ()
+recording::vector_type::make_debug_string ()
 {
   return string::from_printf
     (m_ctxt,
@@ -2549,11 +2622,10 @@ recording::memento_of_get_vector::make_debug_string ()
      m_num_units);
 }
 
-/* Implementation of recording::memento::write_reproducer for volatile
-   types. */
+/* Implementation of recording::memento::write_reproducer for vector types. */
 
 void
-recording::memento_of_get_vector::write_reproducer (reproducer &r)
+recording::vector_type::write_reproducer (reproducer &r)
 {
   const char *id = r.make_identifier (this, "type");
   r.write ("  gcc_jit_type *%s =\n"
@@ -4569,6 +4641,96 @@ recording::memento_of_new_string_literal::write_reproducer (reproducer &r)
     m_value->get_debug_string ());
 }
 
+/* The implementation of class
+   gcc::jit::recording::memento_of_new_rvalue_from_vector.  */
+
+/* The constructor for
+   gcc::jit::recording::memento_of_new_rvalue_from_vector.  */
+
+recording::memento_of_new_rvalue_from_vector::
+memento_of_new_rvalue_from_vector (context *ctxt,
+				   location *loc,
+				   vector_type *type,
+				   rvalue **elements)
+: rvalue (ctxt, loc, type),
+  m_vector_type (type),
+  m_elements ()
+{
+  for (unsigned i = 0; i < type->get_num_units (); i++)
+    m_elements.safe_push (elements[i]);
+}
+
+/* Implementation of pure virtual hook recording::memento::replay_into
+   for recording::memento_of_new_rvalue_from_vector.  */
+
+void
+recording::memento_of_new_rvalue_from_vector::replay_into (replayer *r)
+{
+  auto_vec<playback::rvalue *> playback_elements;
+  playback_elements.create (m_elements.length ());
+  for (unsigned i = 0; i< m_elements.length (); i++)
+    playback_elements.safe_push (m_elements[i]->playback_rvalue ());
+
+  set_playback_obj (r->new_rvalue_from_vector (playback_location (r, m_loc),
+					       m_type->playback_type (),
+					       playback_elements));
+}
+
+/* Implementation of pure virtual hook recording::rvalue::visit_children
+   for recording::memento_of_new_rvalue_from_vector.  */
+
+void
+recording::memento_of_new_rvalue_from_vector::visit_children (rvalue_visitor *v)
+{
+  for (unsigned i = 0; i< m_elements.length (); i++)
+    v->visit (m_elements[i]);
+}
+
+/* Implementation of recording::memento::make_debug_string for
+   vectors.  */
+
+recording::string *
+recording::memento_of_new_rvalue_from_vector::make_debug_string ()
+{
+  comma_separated_string elements (m_elements, get_precedence ());
+
+  /* Now build a string.  */
+  string *result = string::from_printf (m_ctxt,
+					"{%s}",
+					elements.as_char_ptr ());
+
+ return result;
+
+}
+
+/* Implementation of recording::memento::write_reproducer for
+   vectors.  */
+
+void
+recording::memento_of_new_rvalue_from_vector::write_reproducer (reproducer &r)
+{
+  const char *id = r.make_identifier (this, "vector");
+  const char *elements_id = r.make_tmp_identifier ("elements_for_", this);
+  r.write ("  gcc_jit_rvalue *%s[%i] = {\n",
+	   elements_id,
+	   m_elements.length ());
+  for (unsigned i = 0; i< m_elements.length (); i++)
+    r.write ("    %s,\n", r.get_identifier_as_rvalue (m_elements[i]));
+  r.write ("  };\n");
+  r.write ("  gcc_jit_rvalue *%s =\n"
+	   "    gcc_jit_context_new_rvalue_from_vector (%s, /* gcc_jit_context *ctxt */\n"
+	   "                                            %s, /* gcc_jit_location *loc */\n"
+	   "                                            %s, /* gcc_jit_type *vec_type */\n"
+	   "                                            %i, /* size_t num_elements  */ \n"
+	   "                                            %s); /* gcc_jit_rvalue **elements*/\n",
+	   id,
+	   r.get_identifier (get_context ()),
+	   r.get_identifier (m_loc),
+	   r.get_identifier (m_vector_type),
+	   m_elements.length (),
+	   elements_id);
+}
+
 /* The implementation of class gcc::jit::recording::unary_op.  */
 
 /* Implementation of pure virtual hook recording::memento::replay_into
@@ -4982,39 +5144,14 @@ recording::call::visit_children (rvalue_visitor *v)
 recording::string *
 recording::call::make_debug_string ()
 {
-  enum precedence prec = get_precedence ();
   /* First, build a buffer for the arguments.  */
-  /* Calculate length of said buffer.  */
-  size_t sz = 1; /* nil terminator */
-  for (unsigned i = 0; i< m_args.length (); i++)
-    {
-      sz += strlen (m_args[i]->get_debug_string_parens (prec));
-      sz += 2; /* ", " separator */
-    }
-
-  /* Now allocate and populate the buffer.  */
-  char *argbuf = new char[sz];
-  size_t len = 0;
-
-  for (unsigned i = 0; i< m_args.length (); i++)
-    {
-      strcpy (argbuf + len, m_args[i]->get_debug_string_parens (prec));
-      len += strlen (m_args[i]->get_debug_string_parens (prec));
-      if (i + 1 < m_args.length ())
-	{
-	  strcpy (argbuf + len, ", ");
-	  len += 2;
-	}
-    }
-  argbuf[len] = '\0';
+  comma_separated_string args (m_args, get_precedence ());
 
   /* ...and use it to get the string for the call as a whole.  */
   string *result = string::from_printf (m_ctxt,
 					"%s (%s)",
 					m_func->get_debug_string (),
-					argbuf);
-
-  delete[] argbuf;
+					args.as_char_ptr ());
 
   return result;
 }
diff --git a/gcc/jit/jit-recording.h b/gcc/jit/jit-recording.h
index 9123645..6a3fd5d 100644
--- a/gcc/jit/jit-recording.h
+++ b/gcc/jit/jit-recording.h
@@ -149,6 +149,11 @@ public:
   new_string_literal (const char *value);
 
   rvalue *
+  new_rvalue_from_vector (location *loc,
+			  vector_type *type,
+			  rvalue **elements);
+
+  rvalue *
   new_unary_op (location *loc,
 		enum gcc_jit_unary_op op,
 		type *result_type,
@@ -486,6 +491,7 @@ public:
   virtual function_type *dyn_cast_function_type () { return NULL; }
   virtual function_type *as_a_function_type() { gcc_unreachable (); return NULL; }
   virtual struct_ *dyn_cast_struct () { return NULL; }
+  virtual vector_type *dyn_cast_vector_type () { return NULL; }
 
   /* Is it typesafe to copy to this type from rtype?  */
   virtual bool accepts_writes_from (type *rtype)
@@ -690,15 +696,18 @@ private:
 };
 
 /* Result of "gcc_jit_type_get_vector".  */
-class memento_of_get_vector : public decorated_type
+class vector_type : public decorated_type
 {
 public:
-  memento_of_get_vector (type *other_type, size_t num_units)
+  vector_type (type *other_type, size_t num_units)
   : decorated_type (other_type),
     m_num_units (num_units) {}
 
-  /* Strip off the alignment, giving the underlying type.  */
-  type *unqualified () FINAL OVERRIDE { return m_other_type; }
+  size_t get_num_units () const { return m_num_units; }
+
+  vector_type *dyn_cast_vector_type () FINAL OVERRIDE { return this; }
+
+  type *get_element_type () { return m_other_type; }
 
   void replay_into (replayer *) FINAL OVERRIDE;
 
@@ -1358,6 +1367,31 @@ private:
   string *m_value;
 };
 
+class memento_of_new_rvalue_from_vector : public rvalue
+{
+public:
+  memento_of_new_rvalue_from_vector (context *ctxt,
+				     location *loc,
+				     vector_type *type,
+				     rvalue **elements);
+
+  void replay_into (replayer *r) FINAL OVERRIDE;
+
+  void visit_children (rvalue_visitor *) FINAL OVERRIDE;
+
+private:
+  string * make_debug_string () FINAL OVERRIDE;
+  void write_reproducer (reproducer &r) FINAL OVERRIDE;
+  enum precedence get_precedence () const FINAL OVERRIDE
+  {
+    return PRECEDENCE_PRIMARY;
+  }
+
+private:
+  vector_type *m_vector_type;
+  auto_vec<rvalue *> m_elements;
+};
+
 class unary_op : public rvalue
 {
 public:
diff --git a/gcc/jit/libgccjit++.h b/gcc/jit/libgccjit++.h
index 82997c3..9e3c179 100644
--- a/gcc/jit/libgccjit++.h
+++ b/gcc/jit/libgccjit++.h
@@ -187,6 +187,8 @@ namespace gccjit
     rvalue new_rvalue (type pointer_type,
 		       void *value) const;
     rvalue new_rvalue (const std::string &value) const;
+    rvalue new_rvalue (type vector_type,
+		       std::vector<rvalue> elements) const;
 
     /* Generic unary operations...  */
     rvalue new_unary_op (enum gcc_jit_unary_op op,
@@ -897,6 +899,26 @@ context::new_rvalue (const std::string &value) const
 }
 
 inline rvalue
+context::new_rvalue (type vector_type,
+		     std::vector<rvalue> elements) const
+{
+  /* Treat std::vector as an array, relying on it not being resized: */
+  rvalue *as_array_of_wrappers = &elements[0];
+
+  /* Treat the array as being of the underlying pointers, relying on
+     the wrapper type being such a pointer internally.	*/
+  gcc_jit_rvalue **as_array_of_ptrs =
+    reinterpret_cast<gcc_jit_rvalue **> (as_array_of_wrappers);
+
+  return rvalue (
+    gcc_jit_context_new_rvalue_from_vector (m_inner_ctxt,
+					    NULL,
+					    vector_type.get_inner_type (),
+					    elements.size (),
+					    as_array_of_ptrs));
+}
+
+inline rvalue
 context::new_unary_op (enum gcc_jit_unary_op op,
 		       type result_type,
 		       rvalue a,
diff --git a/gcc/jit/libgccjit.c b/gcc/jit/libgccjit.c
index 37cb695..c00acbf 100644
--- a/gcc/jit/libgccjit.c
+++ b/gcc/jit/libgccjit.c
@@ -1335,7 +1335,7 @@ gcc_jit_context_new_binary_op (gcc_jit_context *ctxt,
   RETURN_NULL_IF_FAIL (a, ctxt, loc, "NULL a");
   RETURN_NULL_IF_FAIL (b, ctxt, loc, "NULL b");
   RETURN_NULL_IF_FAIL_PRINTF4 (
-    a->get_type () == b->get_type (),
+    a->get_type ()->unqualified () == b->get_type ()->unqualified (),
     ctxt, loc,
     "mismatching types for binary op:"
     " a: %s (type: %s) b: %s (type: %s)",
@@ -3042,3 +3042,61 @@ gcc_jit_function_get_address (gcc_jit_function *fn,
 
   return (gcc_jit_rvalue *)fn->get_address (loc);
 }
+
+/* Public entrypoint.  See description in libgccjit.h.
+
+   After error-checking, the real work is done by the
+   gcc::jit::recording::context::new_rvalue_from_vector method, in
+   jit-recording.c.  */
+
+extern gcc_jit_rvalue *
+gcc_jit_context_new_rvalue_from_vector (gcc_jit_context *ctxt,
+					gcc_jit_location *loc,
+					gcc_jit_type *vec_type,
+					size_t num_elements,
+					gcc_jit_rvalue **elements)
+{
+  RETURN_NULL_IF_FAIL (ctxt, NULL, loc, "NULL ctxt");
+  JIT_LOG_FUNC (ctxt->get_logger ());
+
+  /* LOC can be NULL.  */
+  RETURN_NULL_IF_FAIL (vec_type, ctxt, loc, "NULL vec_type");
+
+  /* "vec_type" must be a vector type.  */
+  gcc::jit::recording::vector_type *as_vec_type
+    = vec_type->dyn_cast_vector_type ();
+  RETURN_NULL_IF_FAIL_PRINTF1 (as_vec_type, ctxt, loc,
+			       "%s is not a vector type",
+			       vec_type->get_debug_string ());
+
+  /* "num_elements" must match.  */
+  RETURN_NULL_IF_FAIL_PRINTF1 (
+    num_elements == as_vec_type->get_num_units (), ctxt, loc,
+    "num_elements != %zi", as_vec_type->get_num_units ());
+
+  /* "elements must be non-NULL.  */
+  RETURN_NULL_IF_FAIL (elements, ctxt, loc, "NULL elements");
+
+  /* Each of "elements" must be non-NULL and of the correct type.  */
+  gcc::jit::recording::type *element_type
+    = as_vec_type->get_element_type ();
+  for (size_t i = 0; i < num_elements; i++)
+    {
+      RETURN_NULL_IF_FAIL_PRINTF1 (
+	elements[i], ctxt, loc, "NULL elements[%zi]", i);
+      RETURN_NULL_IF_FAIL_PRINTF4 (
+	compatible_types (element_type,
+			  elements[i]->get_type ()),
+	ctxt, loc,
+	"mismatching type for element[%zi] (expected type: %s): %s (type: %s)",
+	i,
+	element_type->get_debug_string (),
+	elements[i]->get_debug_string (),
+	elements[i]->get_type ()->get_debug_string ());
+    }
+
+  return (gcc_jit_rvalue *)ctxt->new_rvalue_from_vector
+    (loc,
+     as_vec_type,
+     (gcc::jit::recording::rvalue **)elements);
+}
diff --git a/gcc/jit/libgccjit.h b/gcc/jit/libgccjit.h
index 18c03fb..f955eb2 100644
--- a/gcc/jit/libgccjit.h
+++ b/gcc/jit/libgccjit.h
@@ -1433,6 +1433,23 @@ gcc_jit_function_get_address (gcc_jit_function *fn,
 			      gcc_jit_location *loc);
 
 
+#define LIBGCCJIT_HAVE_gcc_jit_context_new_rvalue_from_vector
+
+/* Build a vector rvalue from an array of elements.
+
+   "vec_type" should be a vector type, created using gcc_jit_type_get_vector.
+
+   This API entrypoint was added in LIBGCCJIT_ABI_10; you can test for its
+   presence using
+     #ifdef LIBGCCJIT_HAVE_gcc_jit_context_new_rvalue_from_vector
+*/
+extern gcc_jit_rvalue *
+gcc_jit_context_new_rvalue_from_vector (gcc_jit_context *ctxt,
+					gcc_jit_location *loc,
+					gcc_jit_type *vec_type,
+					size_t num_elements,
+					gcc_jit_rvalue **elements);
+
 #ifdef __cplusplus
 }
 #endif /* __cplusplus */
diff --git a/gcc/jit/libgccjit.map b/gcc/jit/libgccjit.map
index 616e364..03f65fd 100644
--- a/gcc/jit/libgccjit.map
+++ b/gcc/jit/libgccjit.map
@@ -165,3 +165,8 @@ LIBGCCJIT_ABI_9 {
   global:
     gcc_jit_function_get_address;
 } LIBGCCJIT_ABI_8;
+
+LIBGCCJIT_ABI_10 {
+  global:
+    gcc_jit_context_new_rvalue_from_vector;
+} LIBGCCJIT_ABI_9;
diff --git a/gcc/testsuite/jit.dg/test-expressions.c b/gcc/testsuite/jit.dg/test-expressions.c
index 548cfa2..f9cc64f 100644
--- a/gcc/testsuite/jit.dg/test-expressions.c
+++ b/gcc/testsuite/jit.dg/test-expressions.c
@@ -920,6 +920,35 @@ verify_get_address (gcc_jit_result *result)
 }
 
 /**********************************************************************
+ Vector values
+ **********************************************************************/
+
+static void
+make_test_of_vectors (gcc_jit_context *ctxt)
+{
+  gcc_jit_type *scalar_type;
+  gcc_jit_type *vec_type;
+  gcc_jit_rvalue *elements[4];
+
+  scalar_type = gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_INT);
+
+  vec_type = gcc_jit_type_get_vector (scalar_type, 4);
+
+  elements[0] = gcc_jit_context_new_rvalue_from_int (ctxt, scalar_type, 1);
+  elements[1] = gcc_jit_context_new_rvalue_from_int (ctxt, scalar_type, -2);
+  elements[2] = gcc_jit_context_new_rvalue_from_int (ctxt, scalar_type, 3);
+  elements[3] = gcc_jit_context_new_rvalue_from_int (ctxt, scalar_type, -4);
+
+  gcc_jit_rvalue *vec_rvalue
+    = gcc_jit_context_new_rvalue_from_vector (ctxt, NULL, vec_type,
+					      4, elements);
+  CHECK_STRING_VALUE (
+    gcc_jit_object_get_debug_string (
+      gcc_jit_rvalue_as_object (vec_rvalue)),
+    "{(int)1, (int)-2, (int)3, (int)-4}");
+}
+
+/**********************************************************************
  Code for harness
  **********************************************************************/
 
@@ -932,6 +961,7 @@ create_code (gcc_jit_context *ctxt, void *user_data)
   make_tests_of_casts (ctxt);
   make_tests_of_dereferences (ctxt);
   make_test_of_get_address (ctxt);
+  make_test_of_vectors (ctxt);
 }
 
 void
diff --git a/gcc/testsuite/jit.dg/test-vector-rvalues.cc b/gcc/testsuite/jit.dg/test-vector-rvalues.cc
new file mode 100644
index 0000000..ac230bf7
--- /dev/null
+++ b/gcc/testsuite/jit.dg/test-vector-rvalues.cc
@@ -0,0 +1,211 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "libgccjit.h"
+
+#include "harness.h"
+
+typedef int v4si __attribute__ ((vector_size (16)));
+typedef unsigned int v4ui __attribute__ ((vector_size (16)));
+typedef float v4f __attribute__ ((vector_size (16)));
+
+static void
+create_vec_fn (gcc_jit_context *ctxt, const char *fnname,
+	       gcc_jit_type *vec_type,
+	       gcc_jit_type *elem_type,
+	       enum gcc_jit_binary_op op)
+{
+  /* Create equivalent to:
+
+       static void
+       FNNAME (V *dst, const V *lhs, E p, E q, E r, E s)
+       {
+	 V pqrs;
+	 pqrs = {p, q, r, s};
+	 *dst = *lhs OP pqrs;
+       }
+
+     where V is "vec_type" (e.g. v4si)
+     and   E is "elem_type" (e.g. int).  */
+
+  gcc_jit_type *ptr_type = gcc_jit_type_get_pointer (vec_type);
+
+  gcc_jit_type *const_type = gcc_jit_type_get_const (vec_type);
+  gcc_jit_type *ptr_to_const_type = gcc_jit_type_get_pointer (const_type);
+
+  gcc_jit_param *dst =
+    gcc_jit_context_new_param (ctxt, NULL, ptr_type, "dst");
+  gcc_jit_param *lhs =
+    gcc_jit_context_new_param (ctxt, NULL, ptr_to_const_type, "lhs");
+  gcc_jit_param *p =
+    gcc_jit_context_new_param (ctxt, NULL, elem_type, "p");
+  gcc_jit_param *q =
+    gcc_jit_context_new_param (ctxt, NULL, elem_type, "q");
+  gcc_jit_param *r =
+    gcc_jit_context_new_param (ctxt, NULL, elem_type, "r");
+  gcc_jit_param *s =
+    gcc_jit_context_new_param (ctxt, NULL, elem_type, "s");
+
+  gcc_jit_type *return_type =
+    gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_VOID);
+
+  gcc_jit_param *params[6] = {dst, lhs, p, q, r, s};
+  gcc_jit_function *func =
+    gcc_jit_context_new_function (ctxt, NULL,
+				  GCC_JIT_FUNCTION_EXPORTED,
+				  return_type,
+				  fnname,
+				  6, params, 0);
+  gcc_jit_block *initial =
+    gcc_jit_function_new_block (func, "initial");
+
+  /* V pqrs; */
+  gcc_jit_lvalue *pqrs
+    = gcc_jit_function_new_local (func, NULL,
+				  vec_type, "pqrs");
+
+  /* pqrs = {p, q, r, s}; */
+  gcc_jit_rvalue *elems[4];
+  elems[0] = gcc_jit_param_as_rvalue (p);
+  elems[1] = gcc_jit_param_as_rvalue (q);
+  elems[2] = gcc_jit_param_as_rvalue (r);
+  elems[3] = gcc_jit_param_as_rvalue (s);
+  gcc_jit_block_add_assignment (
+    initial, NULL,
+    pqrs,
+    gcc_jit_context_new_rvalue_from_vector (ctxt, NULL, vec_type, 4, elems));
+
+  /* (*lhs OP pqrs) */
+  gcc_jit_rvalue *op_result =
+    gcc_jit_context_new_binary_op (
+      ctxt, NULL,
+      op,
+      vec_type,
+      gcc_jit_lvalue_as_rvalue (gcc_jit_rvalue_dereference (gcc_jit_param_as_rvalue (lhs),
+							    NULL)),
+      gcc_jit_lvalue_as_rvalue (pqrs));
+  /* *dst = *lhs OP pqrs; */
+  gcc_jit_block_add_assignment (
+    initial, NULL,
+    gcc_jit_rvalue_dereference (gcc_jit_param_as_rvalue (dst), NULL),
+    op_result);
+  gcc_jit_block_end_with_void_return (initial, NULL);
+}
+
+void
+create_code (gcc_jit_context *ctxt, void *user_data)
+{
+  gcc_jit_type *int_type = gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_INT);
+  gcc_jit_type *unsigned_type
+    = gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_UNSIGNED_INT);
+  gcc_jit_type *float_type = gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_FLOAT);
+
+  gcc_jit_type *v4si_type = gcc_jit_type_get_vector (int_type, 4);
+  gcc_jit_type *v4ui_type = gcc_jit_type_get_vector (unsigned_type, 4);
+  gcc_jit_type *v4f_type = gcc_jit_type_get_vector (float_type, 4);
+
+  create_vec_fn (ctxt, "jit_v4si_add",
+		 v4si_type, int_type, GCC_JIT_BINARY_OP_PLUS);
+  create_vec_fn (ctxt, "jit_v4si_sub",
+		 v4si_type, int_type, GCC_JIT_BINARY_OP_MINUS);
+  create_vec_fn (ctxt, "jit_v4si_mult",
+		 v4si_type, int_type, GCC_JIT_BINARY_OP_MULT);
+  create_vec_fn (ctxt, "jit_v4si_div",
+		 v4si_type, int_type, GCC_JIT_BINARY_OP_DIVIDE);
+
+  create_vec_fn (ctxt, "jit_v4ui_add",
+		 v4ui_type, unsigned_type, GCC_JIT_BINARY_OP_PLUS);
+  create_vec_fn (ctxt, "jit_v4ui_sub",
+		 v4ui_type, unsigned_type, GCC_JIT_BINARY_OP_MINUS);
+  create_vec_fn (ctxt, "jit_v4ui_mult",
+		 v4ui_type, unsigned_type, GCC_JIT_BINARY_OP_MULT);
+  create_vec_fn (ctxt, "jit_v4ui_div",
+		 v4ui_type, unsigned_type, GCC_JIT_BINARY_OP_DIVIDE);
+
+  create_vec_fn (ctxt, "jit_v4f_add",
+		 v4f_type, float_type, GCC_JIT_BINARY_OP_PLUS);
+  create_vec_fn (ctxt, "jit_v4f_sub",
+		 v4f_type, float_type, GCC_JIT_BINARY_OP_MINUS);
+  create_vec_fn (ctxt, "jit_v4f_mult",
+		 v4f_type, float_type, GCC_JIT_BINARY_OP_MULT);
+  create_vec_fn (ctxt, "jit_v4f_div",
+		 v4f_type, float_type, GCC_JIT_BINARY_OP_DIVIDE);
+}
+
+template <typename V>
+void
+check_add (const V &a, const V &b, const V &c)
+{
+  for (int i = 0; i < 4; i++)
+    CHECK_VALUE (c[i], a[i] + b[i]);
+}
+
+template <typename V>
+void
+check_sub (const V &a, const V &b, const V &c)
+{
+  for (int i = 0; i < 4; i++)
+    CHECK_VALUE (c[i], a[i] - b[i]);
+}
+
+template <typename V>
+void
+check_mult (const V &a, const V &b, const V &c)
+{
+  for (int i = 0; i < 4; i++)
+    CHECK_VALUE (c[i], a[i] * b[i]);
+}
+
+template <typename V>
+void
+check_div (const V &a, const V &b, const V &c)
+{
+  for (int i = 0; i < 4; i++)
+    CHECK_VALUE (c[i], a[i] / b[i]);
+}
+
+template <typename V, typename E>
+void
+verify_vec_code (gcc_jit_context *ctxt, gcc_jit_result *result,
+		 const char *fnname,
+		 void (*check_cb) (const V &a, const V &b, const V &c))
+{
+  typedef void (*binop_type) (const V *a, V *b, E p, E q, E r, E s);
+  CHECK_NON_NULL (result);
+  binop_type fn =
+    (binop_type)gcc_jit_result_get_code (result, fnname);
+  CHECK_NON_NULL (fn);
+
+  V dst, lhs, pqrs;
+
+  /* Init.  */
+  for (int i = 0; i < 4; i++)
+    {
+      lhs[i] = i + 5;
+      pqrs[i] = (i + 4) * 3;
+    }
+
+  /* Run jit-compiled code and verify result.  */
+  fn (&dst, &lhs, pqrs[0], pqrs[1], pqrs[2], pqrs[3]);
+  check_cb (lhs, pqrs, dst);
+}
+
+void
+verify_code (gcc_jit_context *ctxt, gcc_jit_result *result)
+{
+  verify_vec_code<v4si, int> (ctxt, result, "jit_v4si_add", check_add);
+  verify_vec_code<v4si, int> (ctxt, result, "jit_v4si_sub", check_sub);
+  verify_vec_code<v4si, int> (ctxt, result, "jit_v4si_mult", check_mult);
+  verify_vec_code<v4si, int> (ctxt, result, "jit_v4si_div", check_div);
+
+  verify_vec_code<v4ui, unsigned int> (ctxt, result, "jit_v4ui_add", check_add);
+  verify_vec_code<v4ui, unsigned int> (ctxt, result, "jit_v4ui_sub", check_sub);
+  verify_vec_code<v4ui, unsigned int> (ctxt, result, "jit_v4ui_mult", check_mult);
+  verify_vec_code<v4ui, unsigned int> (ctxt, result, "jit_v4ui_div", check_div);
+
+  verify_vec_code<v4f, float> (ctxt, result, "jit_v4f_add", check_add);
+  verify_vec_code<v4f, float> (ctxt, result, "jit_v4f_sub", check_sub);
+  verify_vec_code<v4f, float> (ctxt, result, "jit_v4f_mult", check_mult);
+  verify_vec_code<v4f, float> (ctxt, result, "jit_v4f_div", check_div);
+}
-- 
1.8.5.3



More information about the Gcc-patches mailing list