aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorAntoni Boucher <bouanto@zoho.com>2022-05-24 17:45:01 -0400
committerAntoni Boucher <bouanto@zoho.com>2024-11-04 14:32:46 -0500
commit7bb75a5edc1b3c90500e2a78124feac7beefacad (patch)
treec7cd9b05b6e44353b7ac7df7017f8304f9f15fdc /gcc
parente995866cff2866512cd3af24b6ca27a5782aca1f (diff)
downloadgcc-7bb75a5edc1b3c90500e2a78124feac7beefacad.zip
gcc-7bb75a5edc1b3c90500e2a78124feac7beefacad.tar.gz
gcc-7bb75a5edc1b3c90500e2a78124feac7beefacad.tar.bz2
libgccjit: Add gcc_jit_global_set_readonly
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.
Diffstat (limited to 'gcc')
-rw-r--r--gcc/jit/docs/topics/compatibility.rst7
-rw-r--r--gcc/jit/docs/topics/expressions.rst12
-rw-r--r--gcc/jit/jit-playback.cc15
-rw-r--r--gcc/jit/jit-playback.h9
-rw-r--r--gcc/jit/jit-recording.cc9
-rw-r--r--gcc/jit/jit-recording.h11
-rw-r--r--gcc/jit/libgccjit.cc22
-rw-r--r--gcc/jit/libgccjit.h5
-rw-r--r--gcc/jit/libgccjit.map5
-rw-r--r--gcc/testsuite/jit.dg/all-non-failing-tests.h3
-rw-r--r--gcc/testsuite/jit.dg/test-error-assign-readonly.c62
-rw-r--r--gcc/testsuite/jit.dg/test-readonly.c38
12 files changed, 187 insertions, 11 deletions
diff --git a/gcc/jit/docs/topics/compatibility.rst b/gcc/jit/docs/topics/compatibility.rst
index 92c3ed2..96adc03 100644
--- a/gcc/jit/docs/topics/compatibility.rst
+++ b/gcc/jit/docs/topics/compatibility.rst
@@ -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`
diff --git a/gcc/jit/docs/topics/expressions.rst b/gcc/jit/docs/topics/expressions.rst
index 5734f0e..2aabbb8 100644
--- a/gcc/jit/docs/topics/expressions.rst
+++ b/gcc/jit/docs/topics/expressions.rst
@@ -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
-----------------------------------------
diff --git a/gcc/jit/jit-playback.cc b/gcc/jit/jit-playback.cc
index 8dd77e4..f0f0164 100644
--- a/gcc/jit/jit-playback.cc
+++ b/gcc/jit/jit-playback.cc
@@ -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;
diff --git a/gcc/jit/jit-playback.h b/gcc/jit/jit-playback.h
index 77ae2ad..212f0b2 100644
--- a/gcc/jit/jit-playback.h
+++ b/gcc/jit/jit-playback.h
@@ -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);
diff --git a/gcc/jit/jit-recording.cc b/gcc/jit/jit-recording.cc
index 83a36db..c6b9b3c 100644
--- a/gcc/jit/jit-recording.cc
+++ b/gcc/jit/jit-recording.cc
@@ -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 ())
diff --git a/gcc/jit/jit-recording.h b/gcc/jit/jit-recording.h
index abd4f6f..07fdcb9 100644
--- a/gcc/jit/jit-recording.h
+++ b/gcc/jit/jit-recording.h
@@ -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
diff --git a/gcc/jit/libgccjit.cc b/gcc/jit/libgccjit.cc
index eb38da9..cc36ae9 100644
--- a/gcc/jit/libgccjit.cc
+++ b/gcc/jit/libgccjit.cc
@@ -1870,6 +1870,23 @@ gcc_jit_global_set_initializer (gcc_jit_lvalue *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
gcc::jit::recording::memento::as_object method (an lvalue is a
memento), in jit-recording.h. */
@@ -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);
diff --git a/gcc/jit/libgccjit.h b/gcc/jit/libgccjit.h
index 03bfc0f..b1b7277 100644
--- a/gcc/jit/libgccjit.h
+++ b/gcc/jit/libgccjit.h
@@ -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);
diff --git a/gcc/jit/libgccjit.map b/gcc/jit/libgccjit.map
index b02783e..26934dd 100644
--- a/gcc/jit/libgccjit.map
+++ b/gcc/jit/libgccjit.map
@@ -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;
diff --git a/gcc/testsuite/jit.dg/all-non-failing-tests.h b/gcc/testsuite/jit.dg/all-non-failing-tests.h
index 7572132..dfb4dfa 100644
--- a/gcc/testsuite/jit.dg/all-non-failing-tests.h
+++ b/gcc/testsuite/jit.dg/all-non-failing-tests.h
@@ -351,6 +351,9 @@
#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
index 0000000..628bdb8
--- /dev/null
+++ b/gcc/testsuite/jit.dg/test-error-assign-readonly.c
@@ -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
index 0000000..554fa0b
--- /dev/null
+++ b/gcc/testsuite/jit.dg/test-readonly.c
@@ -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" } } */