public inbox for jit@gcc.gnu.org
 help / color / mirror / Atom feed
* [committed] Fix crash accessing builtins in sanitizer.def and after (PR jit/82174)
@ 2017-01-01  0:00 David Malcolm
  2017-01-01  0:00 ` Michael Cree
  0 siblings, 1 reply; 5+ messages in thread
From: David Malcolm @ 2017-01-01  0:00 UTC (permalink / raw)
  To: gcc-patches, jit; +Cc: David Malcolm

Calls to gcc_jit_context_get_builtin_function that accessed builtins
in sanitizer.def and after (or failed to match any builtin) led to
a crash accessing a NULL builtin name.

The entries with the NULL name came from these lines in sanitizer.def:

  /* This has to come before all the sanitizer builtins.  */
  DEF_BUILTIN_STUB(BEGIN_SANITIZER_BUILTINS, (const char *)0)

  [...snip...]

  /* This has to come after all the sanitizer builtins.  */
  DEF_BUILTIN_STUB(END_SANITIZER_BUILTINS, (const char *)0)

This patch updates jit-builtins.c to cope with such entries, fixing the
crash.

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

Committed to trunk as r252769.

gcc/jit/ChangeLog:
	PR jit/82174
	* jit-builtins.c (matches_builtin): Ignore entries with a NULL
	name.

gcc/testsuite/ChangeLog:
	PR jit/82174
	* jit.dg/test-error-gcc_jit_context_get_builtin_function-unknown-builtin.c:
	New test case.
---
 gcc/jit/jit-builtins.c                             |  5 ++++-
 ..._context_get_builtin_function-unknown-builtin.c | 22 ++++++++++++++++++++++
 2 files changed, 26 insertions(+), 1 deletion(-)
 create mode 100644 gcc/testsuite/jit.dg/test-error-gcc_jit_context_get_builtin_function-unknown-builtin.c

diff --git a/gcc/jit/jit-builtins.c b/gcc/jit/jit-builtins.c
index 7840915..35c4db0 100644
--- a/gcc/jit/jit-builtins.c
+++ b/gcc/jit/jit-builtins.c
@@ -68,7 +68,10 @@ matches_builtin (const char *in_name,
 		 const struct builtin_data& bd)
 {
   const bool debug = 0;
-  gcc_assert (bd.name);
+
+  /* Ignore entries with a NULL name.  */
+  if (!bd.name)
+    return false;
 
   if (debug)
     fprintf (stderr, "seen builtin: %s\n", bd.name);
diff --git a/gcc/testsuite/jit.dg/test-error-gcc_jit_context_get_builtin_function-unknown-builtin.c b/gcc/testsuite/jit.dg/test-error-gcc_jit_context_get_builtin_function-unknown-builtin.c
new file mode 100644
index 0000000..b1e389c
--- /dev/null
+++ b/gcc/testsuite/jit.dg/test-error-gcc_jit_context_get_builtin_function-unknown-builtin.c
@@ -0,0 +1,22 @@
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "libgccjit.h"
+
+#include "harness.h"
+
+void
+create_code (gcc_jit_context *ctxt, void *user_data)
+{
+  gcc_jit_context_get_builtin_function (ctxt,
+					"this_is_not_a_builtin");
+}
+
+void
+verify_code (gcc_jit_context *ctxt, gcc_jit_result *result)
+{
+  CHECK_VALUE (result, NULL);
+
+  CHECK_STRING_VALUE (gcc_jit_context_get_first_error (ctxt),
+		      "builtin \"this_is_not_a_builtin\" not found");
+}
-- 
1.8.5.3

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [committed] Fix crash accessing builtins in sanitizer.def and after (PR jit/82174)
  2017-01-01  0:00 [committed] Fix crash accessing builtins in sanitizer.def and after (PR jit/82174) David Malcolm
@ 2017-01-01  0:00 ` Michael Cree
  2017-01-01  0:00   ` [committed] jit: implement gcc_jit_context_new_rvalue_from_vector David Malcolm
  2017-01-01  0:00   ` [committed] Fix crash accessing builtins in sanitizer.def and after (PR jit/82174) David Malcolm
  0 siblings, 2 replies; 5+ messages in thread
From: Michael Cree @ 2017-01-01  0:00 UTC (permalink / raw)
  To: David Malcolm; +Cc: jit

On Thu, Sep 14, 2017 at 04:09:34PM -0400, David Malcolm wrote:
> Calls to gcc_jit_context_get_builtin_function that accessed builtins
> in sanitizer.def and after (or failed to match any builtin) led to
> a crash accessing a NULL builtin name.
  [snip]
> This patch updates jit-builtins.c to cope with such entries, fixing the
> crash.

Thanks for fixing that.

I would now like to get access to the architecture specific builtins.
Any possibility of that being implemented into libgccjit?  My project
is basically dead in the water without them.

Secondly, I am trying to work out how to initialise a vector rvalue
with specified values.  Something in the vein of
gcc_jit_new_rvalue_from_int() but creating a type with vector
attribute and where each individual element is set to some specified
value and it may not be the same value for each element.

The gcc C manual says "vectors can be subscripted as if the vector
were an array [...]" so I tried initialising a vector with
gcc_jit_context_new_array_access() but that fails with errors that
the vector is not a pointer or array at the time of JIT compilation.

Cheers
Michael.

^ permalink raw reply	[flat|nested] 5+ messages in thread

* [committed] jit: implement gcc_jit_context_new_rvalue_from_vector
  2017-01-01  0:00 ` Michael Cree
@ 2017-01-01  0:00   ` David Malcolm
  2017-01-01  0:00   ` [committed] Fix crash accessing builtins in sanitizer.def and after (PR jit/82174) David Malcolm
  1 sibling, 0 replies; 5+ messages in thread
From: David Malcolm @ 2017-01-01  0:00 UTC (permalink / raw)
  To: gcc-patches, jit; +Cc: Michael Cree, David Malcolm

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

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [committed] Fix crash accessing builtins in sanitizer.def and after (PR jit/82174)
  2017-01-01  0:00 ` Michael Cree
  2017-01-01  0:00   ` [committed] jit: implement gcc_jit_context_new_rvalue_from_vector David Malcolm
@ 2017-01-01  0:00   ` David Malcolm
  2017-01-01  0:00     ` Michael Cree
  1 sibling, 1 reply; 5+ messages in thread
From: David Malcolm @ 2017-01-01  0:00 UTC (permalink / raw)
  To: Michael Cree; +Cc: jit

On Sun, 2017-09-17 at 22:05 +1200, Michael Cree wrote:
> On Thu, Sep 14, 2017 at 04:09:34PM -0400, David Malcolm wrote:
> > Calls to gcc_jit_context_get_builtin_function that accessed
> > builtins
> > in sanitizer.def and after (or failed to match any builtin) led to
> > a crash accessing a NULL builtin name.
> 
>   [snip]
> > This patch updates jit-builtins.c to cope with such entries, fixing
> > the
> > crash.
> 
> Thanks for fixing that.
> 
> I would now like to get access to the architecture specific builtins.
> Any possibility of that being implemented into libgccjit?  My project
> is basically dead in the water without them.

I looked at doing that, but it's a little tricky:

<implementation-notes>

In the C and C++ frontends, the target-specific builtins are registered
by TARGET_INIT_BUILTINS, which is called as:

   targetm.init_builtins ();

early on.

On x86 and x86_64 this hook is implemented by ix86_init_builtins, which
does a lot of manipulation using gcc's "tree" type.

Currently in the jit, the name lookup of a builtin happens as the jit
context is being populated, which is much earlier than when
jit_langhook_init is called (when e.g. we could call
targetm.init_builtins (); ) i.e. it's happening way before trees etc
exist

How to fix this? 

Perhaps the jit could keep the string for the builtin, and defer
looking it up (and checking it) to after trees exist: defer checking to
immediately after the tree init happens.  We could then issue early
failure and bail out during the "compile" of the jit context for
builtins that are still unrecognized.

One thing I don't like about this solution (apart from the complexity)
is that it delays error-checking, and it's best to do emit error
messages as early as possible.   Given that the target-specific
builtins seem to all be prefixed with double underscores (e.g.
"__builtin_ia32_aesdec128"), perhaps we could delay the lookup for
builtins that start with double underscores (not all are target-
specific though).  Or maybe just delay it for everything?  Or add a
different entrypoint for accessing such builtins?

</implementation-notes>

> Secondly, I am trying to work out how to initialise a vector rvalue
> with specified values.  Something in the vein of
> gcc_jit_new_rvalue_from_int() but creating a type with vector
> attribute and where each individual element is set to some specified
> value and it may not be the same value for each element.

I've implemented:

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

which is analogous to:

  { element0, element1, ... elementN-1}

in the C frontend.

> The gcc C manual says "vectors can be subscripted as if the vector
> were an array [...]" so I tried initialising a vector with
> gcc_jit_context_new_array_access() but that fails with errors that
> the vector is not a pointer or array at the time of JIT compilation.

I haven't implemented that yet; do you need it?

Thanks
Dave

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [committed] Fix crash accessing builtins in sanitizer.def and after (PR jit/82174)
  2017-01-01  0:00   ` [committed] Fix crash accessing builtins in sanitizer.def and after (PR jit/82174) David Malcolm
@ 2017-01-01  0:00     ` Michael Cree
  0 siblings, 0 replies; 5+ messages in thread
From: Michael Cree @ 2017-01-01  0:00 UTC (permalink / raw)
  To: David Malcolm; +Cc: jit

On Wed, Oct 04, 2017 at 09:56:15AM -0400, David Malcolm wrote:
> On Sun, 2017-09-17 at 22:05 +1200, Michael Cree wrote:
> > On Thu, Sep 14, 2017 at 04:09:34PM -0400, David Malcolm wrote:
> > > Calls to gcc_jit_context_get_builtin_function that accessed
> > > builtins
> > > in sanitizer.def and after (or failed to match any builtin) led to
> > > a crash accessing a NULL builtin name.
> > 
> >   [snip]
> > > This patch updates jit-builtins.c to cope with such entries, fixing
> > > the
> > > crash.
> > 
> > Thanks for fixing that.
> > 
> > I would now like to get access to the architecture specific builtins.
> > Any possibility of that being implemented into libgccjit?  My project
> > is basically dead in the water without them.
> 
> I looked at doing that, but it's a little tricky:

That's a bummer.  The gcc vector optimiser will vectorise standard
operators but unfortunately is rather limited.  It did not, for
example, understand my attempt to implement saturating arithmetic
and proceeded to vectorise every individual operation rather than
replace the sequence with one saturating arithmetic instruction.

If the compiler knew more operators than the standard arithmetic and
logical operations, i.e., if it had a means of specifying min/max
operations and saturating arithmetic operations, and the vector
optimiser then did the conversion to machine specific SIMD
instructions, that would go quite a long way to assisting me.

Doing complex, real/complex and imaginary/complex multiplication
could be really useful to implement generating specific FFTs on the
fly.  I see gcc jit does support the C99 _Complex float/double type
so I must check whether the vector optimiser can produce good SIMD
code for complex arithmetic.  If it doesn't I would probably be back
to wanting machine specific builtins again as some architectures
implement CPU instructions to assist complex multiplication.

> > Secondly, I am trying to work out how to initialise a vector rvalue
> > with specified values.  Something in the vein of
> > gcc_jit_new_rvalue_from_int() but creating a type with vector
> > attribute and where each individual element is set to some specified
> > value and it may not be the same value for each element.
> 
> I've implemented:
> 
> 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);
> 
> which is analogous to:
> 
>   { element0, element1, ... elementN-1}
> 
> in the C frontend.

Brilliant, that should enable one to make good use of the gcc
__builtin_shuffle() builtin which provides a very important SIMD
operation. (Here I am assuming the gcc jit already has access to
that particular builtin; I haven't tested it yet as it was no use
trying without being able to arbitrarily initialise a vector.)

> > The gcc C manual says "vectors can be subscripted as if the vector
> > were an array [...]" so I tried initialising a vector with
> > gcc_jit_context_new_array_access() but that fails with errors that
> > the vector is not a pointer or array at the time of JIT compilation.
> 
> I haven't implemented that yet; do you need it?

No, the above new implemented function provides what is needed.

Thanks,
Michael.

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2017-10-04 19:50 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-01-01  0:00 [committed] Fix crash accessing builtins in sanitizer.def and after (PR jit/82174) David Malcolm
2017-01-01  0:00 ` Michael Cree
2017-01-01  0:00   ` [committed] jit: implement gcc_jit_context_new_rvalue_from_vector David Malcolm
2017-01-01  0:00   ` [committed] Fix crash accessing builtins in sanitizer.def and after (PR jit/82174) David Malcolm
2017-01-01  0:00     ` Michael Cree

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).