diff options
author | Antoni Boucher <bouanto@zoho.com> | 2022-05-24 17:45:01 -0400 |
---|---|---|
committer | Antoni Boucher <bouanto@zoho.com> | 2024-11-04 14:32:46 -0500 |
commit | 7bb75a5edc1b3c90500e2a78124feac7beefacad (patch) | |
tree | c7cd9b05b6e44353b7ac7df7017f8304f9f15fdc /gcc | |
parent | e995866cff2866512cd3af24b6ca27a5782aca1f (diff) | |
download | gcc-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.rst | 7 | ||||
-rw-r--r-- | gcc/jit/docs/topics/expressions.rst | 12 | ||||
-rw-r--r-- | gcc/jit/jit-playback.cc | 15 | ||||
-rw-r--r-- | gcc/jit/jit-playback.h | 9 | ||||
-rw-r--r-- | gcc/jit/jit-recording.cc | 9 | ||||
-rw-r--r-- | gcc/jit/jit-recording.h | 11 | ||||
-rw-r--r-- | gcc/jit/libgccjit.cc | 22 | ||||
-rw-r--r-- | gcc/jit/libgccjit.h | 5 | ||||
-rw-r--r-- | gcc/jit/libgccjit.map | 5 | ||||
-rw-r--r-- | gcc/testsuite/jit.dg/all-non-failing-tests.h | 3 | ||||
-rw-r--r-- | gcc/testsuite/jit.dg/test-error-assign-readonly.c | 62 | ||||
-rw-r--r-- | gcc/testsuite/jit.dg/test-readonly.c | 38 |
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" } } */ |