]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
libgccjit: Add gcc_jit_global_set_readonly
authorAntoni Boucher <bouanto@zoho.com>
Tue, 24 May 2022 21:45:01 +0000 (17:45 -0400)
committerAntoni Boucher <bouanto@zoho.com>
Mon, 4 Nov 2024 19:32:46 +0000 (14:32 -0500)
gcc/jit/ChangeLog:

* docs/topics/compatibility.rst (LIBGCCJIT_ABI_29): New ABI tag.
* docs/topics/expressions.rst: Document gcc_jit_global_set_readonly.
* jit-playback.cc (global_new_decl, new_global,
new_global_initialized): New parameter readonly.
* jit-playback.h (global_new_decl, new_global,
new_global_initialized): New parameter readonly.
* jit-recording.cc (recording::global::replay_into): Use
m_readonly.
(recording::global::write_reproducer): Dump reproducer for
gcc_jit_global_set_readonly.
* jit-recording.h (get_readonly, set_readonly): New methods.
(m_readonly): New attribute.
* libgccjit.cc (gcc_jit_global_set_readonly): New function.
(gcc_jit_block_add_assignment): Check that we don't assign to a
readonly variable.
* libgccjit.h (gcc_jit_global_set_readonly): New function.
(LIBGCCJIT_HAVE_gcc_jit_global_set_readonly): New define.
* libgccjit.map: New function.

gcc/testsuite/ChangeLog:

* jit.dg/all-non-failing-tests.h: Mention test-readonly.c.
* jit.dg/test-error-assign-readonly.c: New test.
* jit.dg/test-readonly.c: New test.

12 files changed:
gcc/jit/docs/topics/compatibility.rst
gcc/jit/docs/topics/expressions.rst
gcc/jit/jit-playback.cc
gcc/jit/jit-playback.h
gcc/jit/jit-recording.cc
gcc/jit/jit-recording.h
gcc/jit/libgccjit.cc
gcc/jit/libgccjit.h
gcc/jit/libgccjit.map
gcc/testsuite/jit.dg/all-non-failing-tests.h
gcc/testsuite/jit.dg/test-error-assign-readonly.c [new file with mode: 0644]
gcc/testsuite/jit.dg/test-readonly.c [new file with mode: 0644]

index 92c3ed24c892e0eaf8d3f372d97aa4a30ecc3829..96adc03fed4d2c15460c1f070ef5f5f143065dbe 100644 (file)
@@ -404,3 +404,10 @@ on functions and variables:
 --------------------
 ``LIBGCCJIT_ABI_28`` covers the addition of
 :func:`gcc_jit_context_new_alignof`
+
+.. _LIBGCCJIT_ABI_29:
+
+``LIBGCCJIT_ABI_29``
+--------------------
+``LIBGCCJIT_ABI_29`` covers the addition of
+:func:`gcc_jit_global_set_readonly`
index 5734f0e5f7e5415917597a61c722cd1746e39e10..2aabbb82a6bcfa8cbe73ac772cdb0e45472ba51a 100644 (file)
@@ -989,6 +989,18 @@ Variables
 
       #ifdef LIBGCCJIT_HAVE_ATTRIBUTES
 
+.. function:: void\
+              gcc_jit_global_set_readonly (gcc_jit_lvalue *global)
+
+   Set the global variable as read-only, meaning you cannot assign to this variable.
+
+   This entrypoint was added in :ref:`LIBGCCJIT_ABI_29`; you can test for its
+   presence using:
+
+   .. code-block:: c
+
+      #ifdef LIBGCCJIT_HAVE_gcc_jit_global_set_readonly
+
 Working with pointers, structs and unions
 -----------------------------------------
 
index 8dd77e4d58717c6c187a2ec6f79b4c897c441672..f0f01648ac19786b99b5c8ca5e301c44c9683f8c 100644 (file)
@@ -723,7 +723,8 @@ global_new_decl (location *loc,
                 const char *name,
                 enum global_var_flags flags,
                 const std::vector<std::pair<gcc_jit_variable_attribute,
-                                            std::string>> &attributes)
+                                            std::string>> &attributes,
+                bool readonly)
 {
   gcc_assert (type);
   gcc_assert (name);
@@ -762,7 +763,7 @@ global_new_decl (location *loc,
       break;
     }
 
-  if (TYPE_READONLY (type_tree))
+  if (TYPE_READONLY (type_tree) || readonly)
     TREE_READONLY (inner) = 1;
 
   if (loc)
@@ -815,10 +816,11 @@ new_global (location *loc,
            const char *name,
            enum global_var_flags flags,
            const std::vector<std::pair<gcc_jit_variable_attribute,
-                                       std::string>> &attributes)
+                                       std::string>> &attributes,
+           bool readonly)
 {
   tree inner =
-    global_new_decl (loc, kind, type, name, flags, attributes);
+    global_new_decl (loc, kind, type, name, flags, attributes, readonly);
 
   return global_finalize_lvalue (inner);
 }
@@ -965,9 +967,10 @@ new_global_initialized (location *loc,
                        const char *name,
                        enum global_var_flags flags,
                        const std::vector<std::pair<gcc_jit_variable_attribute,
-                                                   std::string>> &attributes)
+                                                   std::string>> &attributes,
+                       bool readonly)
 {
-  tree inner = global_new_decl (loc, kind, type, name, flags, attributes);
+  tree inner = global_new_decl (loc, kind, type, name, flags, attributes, readonly);
 
   vec<constructor_elt, va_gc> *constructor_elements = NULL;
 
index 77ae2add4790e1a828b1e67db817379a686daafa..212f0b2662df643353a4c3f403ea978550768d1a 100644 (file)
@@ -130,7 +130,8 @@ public:
              const char *name,
              enum global_var_flags flags,
              const std::vector<std::pair<gcc_jit_variable_attribute,
-                                         std::string>> &attributes);
+                                         std::string>> &attributes,
+             bool readonly);
 
   lvalue *
   new_global_initialized (location *loc,
@@ -144,7 +145,8 @@ public:
                          const std::vector<std::pair<
                                            gcc_jit_variable_attribute,
                                            std::string>>
-                                           &attributes);
+                                           &attributes,
+                         bool readonly);
 
   rvalue *
   new_ctor (location *log,
@@ -337,7 +339,8 @@ private:
                   const char *name,
                   enum global_var_flags flags,
                   const std::vector<std::pair<gcc_jit_variable_attribute,
-                                              std::string>> &attributes);
+                                              std::string>> &attributes,
+                  bool readonly);
   lvalue *
   global_finalize_lvalue (tree inner);
 
index 83a36db653de2d8760eef57cd5c7b25bf8031f5e..c6b9b3c54bf9f057fa78c8851975a626ed0b910f 100644 (file)
@@ -5051,13 +5051,15 @@ recording::global::replay_into (replayer *r)
                                 m_initializer,
                                 playback_string (m_name),
                                 m_flags,
-                                m_string_attributes)
+                                m_string_attributes,
+                                m_readonly)
     : r->new_global (playback_location (r, m_loc),
                     m_kind,
                     m_type->playback_type (),
                     playback_string (m_name),
                     m_flags,
-                    m_string_attributes);
+                    m_string_attributes,
+                    m_readonly);
 
   if (m_tls_model != GCC_JIT_TLS_MODEL_NONE)
     global->set_tls_model (recording::tls_models[m_tls_model]);
@@ -5234,6 +5236,9 @@ recording::global::write_reproducer (reproducer &r)
            gcc_jit_variable_attribute_enum_strings[std::get<0>(attribute)],
            std::get<1>(attribute).c_str());
 
+  if (m_readonly)
+    r.write ("  gcc_jit_global_set_readonly (%s /* gcc_jit_lvalue *lvalue */);\n",
+     id);
 
   if (m_initializer)
     switch (m_type->dereference ()->get_size ())
index abd4f6f8bb3346438fc66326f4fbf5a7b791d03f..07fdcb90773469fbf2508bbd1418ef37295eb540 100644 (file)
@@ -1284,6 +1284,16 @@ public:
 
   void add_string_attribute (gcc_jit_variable_attribute attribute, const char* value);
 
+  bool get_readonly () const
+  {
+    return m_readonly;
+  }
+
+  void set_readonly ()
+  {
+    m_readonly = true;
+  }
+
   virtual const char *access_as_lvalue (reproducer &r);
   virtual bool is_global () const { return false; }
   virtual bool is_local () const { return false; }
@@ -1300,6 +1310,7 @@ protected:
   unsigned m_alignment;
   std::vector<std::pair<gcc_jit_variable_attribute,
              std::string>> m_string_attributes;
+  bool m_readonly = false;
 };
 
 class param : public lvalue
index eb38da91df1ec9f46b00be68b2b11863a64468bc..cc36ae96433250d723740ab20eaf15c97e037273 100644 (file)
@@ -1868,6 +1868,23 @@ 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_readonly method, in
+   jit-recording.cc.  */
+
+extern void
+gcc_jit_global_set_readonly (gcc_jit_lvalue *global)
+{
+  RETURN_IF_FAIL (global, NULL, NULL, "NULL global");
+  RETURN_IF_FAIL_PRINTF1 (global->is_global (), NULL, NULL,
+                              "lvalue \"%s\" not a global",
+                              global->get_debug_string ());
+
+  global->set_readonly ();
+}
+
 /* Public entrypoint.  See description in libgccjit.h.
 
    After error-checking, this calls the trivial
@@ -2880,6 +2897,11 @@ gcc_jit_block_add_assignment (gcc_jit_block *block,
     lvalue->get_type ()->get_debug_string (),
     rvalue->get_debug_string (),
     rvalue->get_type ()->get_debug_string ());
+  RETURN_IF_FAIL_PRINTF1 (
+    !lvalue->get_readonly (),
+    ctxt, loc,
+    "cannot assign to readonly variable: %s",
+    lvalue->get_debug_string ());
 
   gcc::jit::recording::statement *stmt = block->add_assignment (loc, lvalue, rvalue);
 
index 03bfc0f58a533847e11d0c3e20a95b1e91a4ed11..b1b727744984149840455f4e67a2daa1fda103a6 100644 (file)
@@ -1052,6 +1052,11 @@ gcc_jit_global_set_initializer (gcc_jit_lvalue *global,
                                const void *blob,
                                size_t num_bytes);
 
+extern void
+gcc_jit_global_set_readonly (gcc_jit_lvalue *global);
+
+#define LIBGCCJIT_HAVE_gcc_jit_global_set_readonly
+
 /* Upcasting.  */
 extern gcc_jit_object *
 gcc_jit_lvalue_as_object (gcc_jit_lvalue *lvalue);
index b02783ebfb24d1b1094f041b351e3c442ebb4e8c..26934ddf8a0e4ce41af85ae5a950bdda69e3e682 100644 (file)
@@ -294,3 +294,8 @@ LIBGCCJIT_ABI_28 {
   global:
     gcc_jit_context_new_alignof;
 } LIBGCCJIT_ABI_27;
+
+LIBGCCJIT_ABI_29 {
+  global:
+    gcc_jit_global_set_readonly;
+} LIBGCCJIT_ABI_28;
index 75721329ab531dfc08f55f2f2cbd4ce94f652dec..dfb4dfa98db9514f180e432d1e37e1b4d1185366 100644 (file)
 #undef create_code
 #undef verify_code
 
+/* test-readonly.c: This can't be in the testcases array as it
+   is target-specific.  */
+
 /* test-restrict.c: This can't be in the testcases array as it needs
    the `-O3` flag.  */
 
diff --git a/gcc/testsuite/jit.dg/test-error-assign-readonly.c b/gcc/testsuite/jit.dg/test-error-assign-readonly.c
new file mode 100644 (file)
index 0000000..628bdb8
--- /dev/null
@@ -0,0 +1,62 @@
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "libgccjit.h"
+
+#include "harness.h"
+
+void
+create_code (gcc_jit_context *ctxt, void *user_data)
+{
+  /* Let's try to inject the equivalent of:
+
+     const long integer = 10;
+
+     void
+     test_fn ()
+     {
+        integer = 12;
+     }
+
+     and verify that the API complains about assigning to a read-only
+     variable.
+  */
+  gcc_jit_type *void_type =
+    gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_VOID);
+  gcc_jit_type *long_type =
+    gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_LONG);
+
+  gcc_jit_function *func =
+    gcc_jit_context_new_function (ctxt, NULL,
+                                  GCC_JIT_FUNCTION_EXPORTED,
+                                  void_type,
+                                  "test_fn",
+                                  0, NULL,
+                                  0);
+  gcc_jit_block *initial =
+    gcc_jit_function_new_block (func, "initial");
+
+  gcc_jit_lvalue *integer =
+    gcc_jit_context_new_global (
+      ctxt, NULL, GCC_JIT_GLOBAL_EXPORTED, long_type, "integer");
+
+  gcc_jit_rvalue *ten = gcc_jit_context_new_rvalue_from_int (ctxt, long_type, 10);
+  gcc_jit_global_set_initializer_rvalue (integer, ten);
+  gcc_jit_global_set_readonly(integer);
+
+  gcc_jit_rvalue *twelve = gcc_jit_context_new_rvalue_from_int (ctxt, long_type, 12);
+  gcc_jit_block_add_assignment(initial, NULL, integer, twelve);
+
+  gcc_jit_block_end_with_void_return (initial, NULL);
+}
+
+void
+verify_code (gcc_jit_context *ctxt, gcc_jit_result *result)
+{
+  CHECK_VALUE (result, NULL);
+
+  /* Verify that the correct error messages were emitted.  */
+  CHECK_STRING_VALUE (gcc_jit_context_get_first_error (ctxt),
+                     "gcc_jit_block_add_assignment:"
+                     " cannot assign to readonly variable: integer");
+}
diff --git a/gcc/testsuite/jit.dg/test-readonly.c b/gcc/testsuite/jit.dg/test-readonly.c
new file mode 100644 (file)
index 0000000..554fa0b
--- /dev/null
@@ -0,0 +1,38 @@
+/* { dg-do compile { target x86_64-*-* } } */
+
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "libgccjit.h"
+
+/* We don't want set_options() in harness.h to set -O3 so our little local
+   is optimized away. */
+#define TEST_ESCHEWS_SET_OPTIONS
+static void set_options (gcc_jit_context *ctxt, const char *argv0)
+{
+}
+
+#define TEST_COMPILING_TO_FILE
+#define OUTPUT_KIND      GCC_JIT_OUTPUT_KIND_ASSEMBLER
+#define OUTPUT_FILENAME  "output-of-test-readonly.c.s"
+#include "harness.h"
+
+void
+create_code (gcc_jit_context *ctxt, void *user_data)
+{
+  /* Let's try to inject the equivalent of:
+     const int foo;
+  */
+  gcc_jit_type *int_type =
+    gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_INT);
+  gcc_jit_lvalue *foo =
+    gcc_jit_context_new_global (
+      ctxt, NULL, GCC_JIT_GLOBAL_EXPORTED, int_type, "foo");
+
+  gcc_jit_rvalue *ten = gcc_jit_context_new_rvalue_from_int (ctxt, int_type, 10);
+  gcc_jit_global_set_initializer_rvalue (foo, ten);
+  gcc_jit_global_set_readonly(foo);
+}
+
+/* { dg-final { jit-verify-output-file-was-created "" } } */
+/* { dg-final { jit-verify-assembler-output ".section\t.rodata" } } */