public inbox for jit@gcc.gnu.org
 help / color / mirror / Atom feed
* [PATCH] libgccjit: Add function to set the initial value of a global variable [PR96089]
@ 2021-05-21  1:27 Antoni Boucher
  2021-06-11 20:44 ` Antoni Boucher
  0 siblings, 1 reply; 12+ messages in thread
From: Antoni Boucher @ 2021-05-21  1:27 UTC (permalink / raw)
  To: jit, gcc-patches

[-- Attachment #1: Type: text/plain, Size: 569 bytes --]

Hi.

I made this patch to set an arbitrary value to a global variable.

This patch suffers from the same issue as inline assembly
(https://gcc.gnu.org/bugzilla/show_bug.cgi?id=100380), i.e. it
segfaults if the `rvalue` is created after the global variable.
It seems to be a design issue so I'm not sure what would be the fix for
it and having it fixed would allow me to test this new function much
more and see if things are missing (i.e. it might require a way to
create a constant struct).
See the link above for an explanation of this issue.

Thanks for the review.

[-- Attachment #2: 0001-Add-function-to-set-the-initial-value-of-a-global-va.patch --]
[-- Type: text/x-patch, Size: 12334 bytes --]

From 0a5fd7f759e1bd7becc993f01bdcf84ff8fc5fd5 Mon Sep 17 00:00:00 2001
From: Antoni Boucher <bouanto@zoho.com>
Date: Sat, 15 May 2021 10:54:36 -0400
Subject: [PATCH] Add function to set the initial value of a global variable
 [PR96089]

2021-05-20  Antoni Boucher  <bouanto@zoho.com>

    gcc/jit/
            PR target/96089
            * docs/topics/compatibility.rst (LIBGCCJIT_ABI_19): New ABI
            tag.
            * docs/topics/expressions.rst: Add documentation for the
            function gcc_jit_global_set_initializer_value.
            * jit-playback.c: New function (new_global_with_value).
            * jit-playback.h: New function (new_global_with_value).
            * jit-recording.c: Add support for setting a value to a
            global variable.
            * jit-recording.h: New function (set_initializer_value) and
            new field m_initializer_value.
            * libgccjit.c: New macro RETURN_IF_FAIL_PRINTF5 and new
            function (gcc_jit_global_set_initializer_value).
            * libgccjit.h: New function (gcc_jit_global_set_initializer_value).
            * libgccjit.map (LIBGCCJIT_ABI_19): New ABI tag.

    gcc/testsuite/
            PR target/96089
            * jit.dg/test-global-set-initializer.c: Add test for the new
            function (gcc_jit_global_set_initializer_value).
---
 gcc/jit/docs/topics/compatibility.rst         |  9 ++++
 gcc/jit/docs/topics/expressions.rst           | 14 ++++++
 gcc/jit/jit-playback.c                        | 18 ++++++++
 gcc/jit/jit-playback.h                        |  7 +++
 gcc/jit/jit-recording.c                       | 34 ++++++++++++---
 gcc/jit/jit-recording.h                       |  8 ++++
 gcc/jit/libgccjit.c                           | 43 +++++++++++++++++++
 gcc/jit/libgccjit.h                           | 13 ++++++
 gcc/jit/libgccjit.map                         | 14 ++++++
 .../jit.dg/test-global-set-initializer.c      | 15 +++++++
 10 files changed, 169 insertions(+), 6 deletions(-)

diff --git a/gcc/jit/docs/topics/compatibility.rst b/gcc/jit/docs/topics/compatibility.rst
index 239b6aa1a92..666eb3a1c51 100644
--- a/gcc/jit/docs/topics/compatibility.rst
+++ b/gcc/jit/docs/topics/compatibility.rst
@@ -243,3 +243,12 @@ embedding assembler instructions:
   * :func:`gcc_jit_extended_asm_add_input_operand`
   * :func:`gcc_jit_extended_asm_add_clobber`
   * :func:`gcc_jit_context_add_top_level_asm`
+
+.. _LIBGCCJIT_ABI_19:
+
+``LIBGCCJIT_ABI_19``
+-----------------------
+``LIBGCCJIT_ABI_19`` covers the addition of an API entrypoint to set the value
+of a global variable:
+
+  * :func:`gcc_jit_global_set_initializer_value`
diff --git a/gcc/jit/docs/topics/expressions.rst b/gcc/jit/docs/topics/expressions.rst
index 396259ef07e..f638cb68fdd 100644
--- a/gcc/jit/docs/topics/expressions.rst
+++ b/gcc/jit/docs/topics/expressions.rst
@@ -603,6 +603,20 @@ Global variables
 
       #ifdef LIBGCCJIT_HAVE_gcc_jit_global_set_initializer
 
+.. function:: void
+              gcc_jit_global_set_initializer_value (gcc_jit_lvalue *global,\
+                                                    gcc_jit_rvalue *value)
+
+   Set an initializer for ``global`` using the specified value.
+   ``global`` must be the same type as ``value``.
+
+   This entrypoint was added in :ref:`LIBGCCJIT_ABI_19`; you can test for
+   its presence using
+
+   .. code-block:: c
+
+      #ifdef LIBGCCJIT_HAVE_gcc_jit_global_set_initializer_value
+
 Working with pointers, structs and unions
 -----------------------------------------
 
diff --git a/gcc/jit/jit-playback.c b/gcc/jit/jit-playback.c
index c6136301243..d86701a8ae6 100644
--- a/gcc/jit/jit-playback.c
+++ b/gcc/jit/jit-playback.c
@@ -664,6 +664,24 @@ new_global_initialized (location *loc,
   return global_finalize_lvalue (inner);
 }
 
+playback::lvalue *
+playback::context::
+new_global_with_value (location *loc,
+		       enum gcc_jit_global_kind kind,
+		       type *type,
+		       playback::rvalue *value,
+		       const char *name)
+{
+  tree inner = global_new_decl (loc, kind, type, name);
+
+  tree inner_type = type->as_tree ();
+  tree initial = value->as_tree ();
+  gcc_assert (TREE_CONSTANT (initial));
+  DECL_INITIAL (inner) = initial;
+
+  return global_finalize_lvalue (inner);
+}
+
 /* Implementation of the various
       gcc::jit::playback::context::new_rvalue_from_const <HOST_TYPE>
    methods.
diff --git a/gcc/jit/jit-playback.h b/gcc/jit/jit-playback.h
index 825a3e172e9..958284df539 100644
--- a/gcc/jit/jit-playback.h
+++ b/gcc/jit/jit-playback.h
@@ -120,6 +120,13 @@ public:
                           const void *initializer,
                           const char *name);
 
+  lvalue*
+  new_global_with_value (location *loc,
+			 enum gcc_jit_global_kind kind,
+			 type *type,
+			 rvalue *value,
+			 const char *name);
+
   template <typename HOST_TYPE>
   rvalue *
   new_rvalue_from_const (type *type,
diff --git a/gcc/jit/jit-recording.c b/gcc/jit/jit-recording.c
index 117ff70114c..a26e4928084 100644
--- a/gcc/jit/jit-recording.c
+++ b/gcc/jit/jit-recording.c
@@ -4547,20 +4547,34 @@ recording::block::dump_edges_to_dot (pretty_printer *pp)
 void
 recording::global::replay_into (replayer *r)
 {
-  set_playback_obj (
-    m_initializer
-    ? r->new_global_initialized (playback_location (r, m_loc),
+  playback::lvalue * obj;
+  if (m_initializer)
+  {
+      obj = r->new_global_initialized (playback_location (r, m_loc),
 				 m_kind,
 				 m_type->playback_type (),
 				 m_type->dereference ()->get_size (),
 				 m_initializer_num_bytes
 				 / m_type->dereference ()->get_size (),
 				 m_initializer,
-				 playback_string (m_name))
-    : r->new_global (playback_location (r, m_loc),
+				 playback_string (m_name));
+  }
+  else if (m_initializer_value)
+  {
+      obj = r->new_global_with_value (playback_location (r, m_loc),
+				 m_kind,
+				 m_type->playback_type (),
+				 m_initializer_value->playback_rvalue (),
+				 playback_string (m_name));
+  }
+  else
+  {
+      obj = r->new_global (playback_location (r, m_loc),
 		     m_kind,
 		     m_type->playback_type (),
-		     playback_string (m_name)));
+		     playback_string (m_name));
+  }
+  set_playback_obj (obj);
 }
 
 /* Override the default implementation of
@@ -4675,6 +4689,14 @@ recording::global::write_reproducer (reproducer &r)
     r.get_identifier_as_type (get_type ()),
     m_name->get_debug_string ());
 
+  if (m_initializer_value)
+  {
+    r.write ("  gcc_jit_global_set_initializer_value (%s, /* gcc_jit_lvalue *global */\n"
+      "    %s/* gcc_jit_rvalue *value */);\n",
+    id,
+    r.get_identifier_as_rvalue (m_initializer_value));
+  }
+
   if (m_initializer)
     switch (m_type->dereference ()->get_size ())
       {
diff --git a/gcc/jit/jit-recording.h b/gcc/jit/jit-recording.h
index 03fa1160cf0..61de2e1dcd4 100644
--- a/gcc/jit/jit-recording.h
+++ b/gcc/jit/jit-recording.h
@@ -1360,6 +1360,7 @@ public:
     m_name (name)
   {
     m_initializer = NULL;
+    m_initializer_value = NULL;
     m_initializer_num_bytes = 0;
   }
   ~global ()
@@ -1386,6 +1387,12 @@ public:
     m_initializer_num_bytes = num_bytes;
   }
 
+  void
+  set_initializer_value (rvalue* value)
+  {
+    m_initializer_value = value;
+  }
+
 private:
   string * make_debug_string () FINAL OVERRIDE { return m_name; }
   template <typename T>
@@ -1400,6 +1407,7 @@ private:
   enum gcc_jit_global_kind m_kind;
   string *m_name;
   void *m_initializer;
+  rvalue *m_initializer_value;
   size_t m_initializer_num_bytes;
 };
 
diff --git a/gcc/jit/libgccjit.c b/gcc/jit/libgccjit.c
index 7fa948007ad..b7fd4d9bebb 100644
--- a/gcc/jit/libgccjit.c
+++ b/gcc/jit/libgccjit.c
@@ -269,6 +269,17 @@ struct gcc_jit_extended_asm : public gcc::jit::recording::extended_asm
       }								\
   JIT_END_STMT
 
+#define RETURN_IF_FAIL_PRINTF5(TEST_EXPR, CTXT, LOC, ERR_FMT, A0, A1, A2, A3, \
+			       A4) \
+  JIT_BEGIN_STMT							\
+    if (!(TEST_EXPR))							\
+      {								\
+	jit_error ((CTXT), (LOC), "%s: " ERR_FMT,			\
+		   __func__, (A0), (A1), (A2), (A3), (A4));		\
+	return;							\
+      }								\
+  JIT_END_STMT
+
 /* Check that BLOCK is non-NULL, and that it's OK to add statements to
    it.  This will fail if BLOCK has already been terminated by some
    kind of jump or a return.  */
@@ -1161,6 +1172,38 @@ gcc_jit_global_set_initializer (gcc_jit_lvalue *global,
   return global;
 }
 
+/* Public entrypoint.  See description in libgccjit.h.
+
+   After error-checking, the real work is done by the
+   gcc::jit::recording::global::set_initializer_value method, in
+   jit-recording.c.  */
+
+void
+gcc_jit_global_set_initializer_value (gcc_jit_lvalue *global,
+				gcc_jit_rvalue *value)
+{
+  RETURN_IF_FAIL (global, NULL, NULL, "NULL global");
+  RETURN_IF_FAIL (value, NULL, NULL, "NULL value");
+  RETURN_IF_FAIL_PRINTF1 (global->is_global (), NULL, NULL,
+			       "lvalue \"%s\" not a global",
+			       global->get_debug_string ());
+
+      RETURN_IF_FAIL_PRINTF5 (
+	compatible_types (global->get_type (),
+			  value->get_type ()),
+	NULL, NULL,
+	"mismatching types for global \"%s\":"
+	" assignment to global %s (type: %s) from %s (type: %s)",
+	global->get_debug_string (),
+	global->get_debug_string (),
+	global->get_type ()->get_debug_string (),
+	value->get_debug_string (),
+	value->get_type ()->get_debug_string ());
+
+  reinterpret_cast <gcc::jit::recording::global *> (global)
+    ->set_initializer_value (value);
+}
+
 /* Public entrypoint.  See description in libgccjit.h.
 
    After error-checking, this calls the trivial
diff --git a/gcc/jit/libgccjit.h b/gcc/jit/libgccjit.h
index 5c722c2c57f..98762d05271 100644
--- a/gcc/jit/libgccjit.h
+++ b/gcc/jit/libgccjit.h
@@ -810,6 +810,19 @@ gcc_jit_global_set_initializer (gcc_jit_lvalue *global,
 				const void *blob,
 				size_t num_bytes);
 
+#define LIBGCCJIT_HAVE_gcc_jit_global_set_initializer_value
+
+/* Set an initial value for a global, which must be a constant.
+
+   This API entrypoint was added in LIBGCCJIT_ABI_19; you can test for its
+   presence using
+     #ifdef LIBGCCJIT_HAVE_gcc_jit_global_set_initializer_value
+*/
+
+extern void
+gcc_jit_global_set_initializer_value (gcc_jit_lvalue *global,
+				gcc_jit_rvalue *value);
+
 /* Upcasting.  */
 extern gcc_jit_object *
 gcc_jit_lvalue_as_object (gcc_jit_lvalue *lvalue);
diff --git a/gcc/jit/libgccjit.map b/gcc/jit/libgccjit.map
index 337ea6c7fe4..a0e72c925d0 100644
--- a/gcc/jit/libgccjit.map
+++ b/gcc/jit/libgccjit.map
@@ -205,3 +205,17 @@ LIBGCCJIT_ABI_15 {
     gcc_jit_extended_asm_add_clobber;
     gcc_jit_context_add_top_level_asm;
 } LIBGCCJIT_ABI_14;
+
+LIBGCCJIT_ABI_16 {
+} LIBGCCJIT_ABI_15;
+
+LIBGCCJIT_ABI_17 {
+} LIBGCCJIT_ABI_16;
+
+LIBGCCJIT_ABI_18 {
+} LIBGCCJIT_ABI_17;
+
+LIBGCCJIT_ABI_19 {
+  global:
+    gcc_jit_global_set_initializer_value;
+} LIBGCCJIT_ABI_18;
diff --git a/gcc/testsuite/jit.dg/test-global-set-initializer.c b/gcc/testsuite/jit.dg/test-global-set-initializer.c
index d38aba7d73f..418ed7dcf3f 100644
--- a/gcc/testsuite/jit.dg/test-global-set-initializer.c
+++ b/gcc/testsuite/jit.dg/test-global-set-initializer.c
@@ -21,6 +21,7 @@ create_code (gcc_jit_context *ctxt, void *user_data)
      signed char bin_blob1[] = { 0xc, 0xa, 0xf, 0xf, 0xe };
      unsigned bin_blob2[] = { 0x3, 0x2, 0x1, 0x0, 0x1, 0x2, 0x3 };
      unsigned char bin_blob3[4096]...
+     unsigned int integer = 42;
   */
   gcc_jit_type *unsigned_char_type =
     gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_UNSIGNED_CHAR);
@@ -56,6 +57,16 @@ create_code (gcc_jit_context *ctxt, void *user_data)
 				      sizeof (test_blob3)),
       "bin_blob3");
   gcc_jit_global_set_initializer (glob, test_blob3, sizeof (test_blob3));
+
+  gcc_jit_rvalue *forty_two = gcc_jit_context_new_rvalue_from_int (
+      ctxt, unsigned_type, 42);
+
+  glob =
+    gcc_jit_context_new_global (
+      ctxt, NULL, GCC_JIT_GLOBAL_EXPORTED,
+      unsigned_type,
+      "integer");
+  gcc_jit_global_set_initializer_value (glob, forty_two);
 }
 
 void
@@ -75,4 +86,8 @@ verify_code (gcc_jit_context *ctxt, gcc_jit_result *result)
   CHECK_NON_NULL (glob);
   CHECK_VALUE (memcmp (test_blob3, glob, sizeof (test_blob3)), 0);
 
+  glob = gcc_jit_result_get_global (result, "integer");
+  CHECK_NON_NULL (glob);
+  int *value = glob;
+  CHECK_VALUE (*value, 42);
 }
-- 
2.31.1


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

end of thread, other threads:[~2021-12-06 10:56 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-05-21  1:27 [PATCH] libgccjit: Add function to set the initial value of a global variable [PR96089] Antoni Boucher
2021-06-11 20:44 ` Antoni Boucher
2021-11-23  2:01   ` Antoni Boucher
2021-11-23 10:51     ` SV: " Petter Tomner
2021-11-23 14:10       ` Antoni Boucher
2021-11-24 13:38         ` SV: " Petter Tomner
2021-11-30  1:34       ` David Malcolm
2021-11-30 14:37         ` SV: " Petter Tomner
2021-12-02  0:07           ` David Malcolm
2021-12-02 22:58             ` Antoni Boucher
2021-12-06 10:56               ` SV: " Petter Tomner
2021-12-06 10:51             ` Petter Tomner

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