From: Andrea Corallo <andrea.corallo@arm.com>
To: David Malcolm <dmalcolm@redhat.com>
Cc: jit@gcc.gnu.org, nd@arm.com, gcc-patches@gcc.gnu.org
Subject: Re: [PATCH] libgccjit: Add new gcc_jit_context_new_blob entry point
Date: Mon, 03 Aug 2020 10:07:53 +0200 [thread overview]
Message-ID: <gkr3654f8yu.fsf@arm.com> (raw)
In-Reply-To: <22479e6a6a1e27df07a3d2c2cfb8c6c8420a7d3d.camel@redhat.com> (David Malcolm's message of "Fri, 24 Jul 2020 18:12:22 -0400")
[-- Attachment #1: Type: text/plain, Size: 3245 bytes --]
David Malcolm <dmalcolm@redhat.com> writes:
> On Fri, 2020-07-24 at 18:05 -0400, David Malcolm via Gcc-patches wrote:
>
> [...]
>
>> I haven't thought this through in detail, and I'm not sure exactly
>> how
>> it would work for arbitrary types, but I thought it worth sharing.
>> (For example I can think of nasty issues if we ever want to support
>> cross-compilation, e.g. where sizeof types or endianness differs
>> between host and target).
>
> ...which is an argument in favor of retaining the name "blob", perhaps
> as the name of the argument in the header file e.g.:
>
> extern void
> gcc_jit_global_set_initializer (gcc_jit_lvalue *global,
> const void *blob,
> size_t num_bytes);
>
>
> as a subtle hint to the user that they need to be wary about binary
> layouts ("here be dragons").
>
> [...]
Hi Dave & all,
following up this is my take on the implementation of:
gcc_jit_global_set_initializer (gcc_jit_lvalue *global,
const void *blob,
size_t num_bytes);
'global' must be an array but in the seek of generality it now supports
all the various integral types and is not limited to char[].
As you anticipated the implementation I came up is currently not safe
for cross-compilation, not sure is requirement tho.
make check-jit is clean
Feedback very welcome
Thanks!
Andrea
gcc/jit/ChangeLog
2020-08-01 Andrea Corallo <andrea.corallo@arm.com>
* docs/topics/compatibility.rst (LIBGCCJIT_ABI_14): New ABI tag.
* docs/topics/expressions.rst (gcc_jit_global_set_initializer):
Document new entry point in section 'Global variables'.
* jit-playback.c (global_new_decl, global_finalize_lvalue): New
method.
(playback::context::new_global): Make use of global_new_decl,
global_finalize_lvalue.
(load_blob_in_ctor): New template function in use by the
following.
(playback::context::new_global_initialized): New method.
* jit-playback.h (class context): Decl 'new_global_initialized',
'global_new_decl', 'global_finalize_lvalue'.
(lvalue::set_initializer): Add implementation.
* jit-recording.c (recording::memento_of_get_pointer::get_size)
(recording::memento_of_get_type::get_size): Add implementation.
(recording::global::write_initializer_reproducer): New function in
use by 'recording::global::write_reproducer'.
(recording::global::replay_into)
(recording::global::write_to_dump)
(recording::global::write_reproducer): Handle
initialized case.
* jit-recording.h (class type): Decl 'get_size' and
'num_elements'.
* libgccjit++.h (class lvalue): Declare new 'set_initializer'
method.
(class lvalue): Decl 'is_global' and 'set_initializer'.
(class class global) Decl 'write_initializer_reproducer'. Add
'm_initializer', 'm_initializer_num_bytes' fields. Implement
'set_initializer'.
* libgccjit.c (gcc_jit_global_set_initializer): New function.
* libgccjit.h (gcc_jit_global_set_initializer): New function
declaration.
* libgccjit.map (LIBGCCJIT_ABI_14): New ABI tag.
gcc/testsuite/ChangeLog
2020-08-01 Andrea Corallo <andrea.corallo@arm.com>
* jit.dg/all-non-failing-tests.h: Add test-blob.c.
* jit.dg/test-global-set-initializer.c: New testcase.
[-- Attachment #2: 0001-Add-new-gcc_jit_global_set_initializer-entry-point.patch --]
[-- Type: text/plain, Size: 24482 bytes --]
From 74bd96fde6d4baed978555279d17898b989c00ad Mon Sep 17 00:00:00 2001
From: Andrea Corallo <andrea.corallo@arm.com>
Date: Sat, 30 May 2020 10:33:08 +0100
Subject: [PATCH] Add new gcc_jit_global_set_initializer entry point
gcc/jit/ChangeLog
2020-08-01 Andrea Corallo <andrea.corallo@arm.com>
* docs/topics/compatibility.rst (LIBGCCJIT_ABI_14): New ABI tag.
* docs/topics/expressions.rst (gcc_jit_global_set_initializer):
Document new entry point in section 'Global variables'.
* jit-playback.c (global_new_decl, global_finalize_lvalue): New
method.
(playback::context::new_global): Make use of global_new_decl,
global_finalize_lvalue.
(load_blob_in_ctor): New template function in use by the
following.
(playback::context::new_global_initialized): New method.
* jit-playback.h (class context): Decl 'new_global_initialized',
'global_new_decl', 'global_finalize_lvalue'.
(lvalue::set_initializer): Add implementation.
* jit-recording.c (recording::memento_of_get_pointer::get_size)
(recording::memento_of_get_type::get_size): Add implementation.
(recording::global::write_initializer_reproducer): New function in
use by 'recording::global::write_reproducer'.
(recording::global::replay_into)
(recording::global::write_to_dump)
(recording::global::write_reproducer): Handle
initialized case.
* jit-recording.h (class type): Decl 'get_size' and
'num_elements'.
* libgccjit++.h (class lvalue): Declare new 'set_initializer'
method.
(class lvalue): Decl 'is_global' and 'set_initializer'.
(class class global) Decl 'write_initializer_reproducer'. Add
'm_initializer', 'm_initializer_num_bytes' fields. Implement
'set_initializer'.
* libgccjit.c (gcc_jit_global_set_initializer): New function.
* libgccjit.h (gcc_jit_global_set_initializer): New function
declaration.
* libgccjit.map (LIBGCCJIT_ABI_14): New ABI tag.
gcc/testsuite/ChangeLog
2020-08-01 Andrea Corallo <andrea.corallo@arm.com>
* jit.dg/all-non-failing-tests.h: Add test-blob.c.
* jit.dg/test-global-set-initializer.c: New testcase.
---
gcc/jit/docs/topics/compatibility.rst | 7 +
gcc/jit/docs/topics/expressions.rst | 21 +++
gcc/jit/jit-playback.c | 105 +++++++++++++-
gcc/jit/jit-playback.h | 17 +++
gcc/jit/jit-recording.c | 137 +++++++++++++++++-
gcc/jit/jit-recording.h | 26 ++++
gcc/jit/libgccjit++.h | 10 ++
gcc/jit/libgccjit.c | 36 +++++
gcc/jit/libgccjit.h | 14 ++
gcc/jit/libgccjit.map | 7 +-
gcc/testsuite/jit.dg/all-non-failing-tests.h | 7 +
.../jit.dg/test-global-set-initializer.c | 78 ++++++++++
12 files changed, 453 insertions(+), 12 deletions(-)
create mode 100644 gcc/testsuite/jit.dg/test-global-set-initializer.c
diff --git a/gcc/jit/docs/topics/compatibility.rst b/gcc/jit/docs/topics/compatibility.rst
index bb3387fa583b..6bfa101ed718 100644
--- a/gcc/jit/docs/topics/compatibility.rst
+++ b/gcc/jit/docs/topics/compatibility.rst
@@ -219,3 +219,10 @@ entrypoints:
* :func:`gcc_jit_version_minor`
* :func:`gcc_jit_version_patchlevel`
+
+.. _LIBGCCJIT_ABI_14:
+
+``LIBGCCJIT_ABI_14``
+--------------------
+``LIBGCCJIT_ABI_14`` covers the addition of
+:func:`gcc_jit_global_set_initializer`
diff --git a/gcc/jit/docs/topics/expressions.rst b/gcc/jit/docs/topics/expressions.rst
index d783ceea51a8..7699dcfd27be 100644
--- a/gcc/jit/docs/topics/expressions.rst
+++ b/gcc/jit/docs/topics/expressions.rst
@@ -582,6 +582,27 @@ Global variables
referring to it. Analogous to using an "extern" global from a
header file.
+.. function:: gcc_jit_lvalue *\
+ gcc_jit_global_set_initializer (gcc_jit_lvalue *global,\
+ const void *blob,\
+ size_t num_bytes)
+
+ Set an initializer for an object using the memory content pointed
+ by ``blob`` for ``num_bytes``. ``global`` must be an arrays of an
+ integral type.
+
+ The parameter ``blob`` must be non-NULL. The call copies the memory
+ pointed by ``blob`` for ``num_bytes`` bytes, so it is valid to pass
+ in a pointer to an on-stack buffer. The content will be stored in
+ the compilation unit and used as initialization value of the array.
+
+ This entrypoint was added in :ref:`LIBGCCJIT_ABI_14`; you can test for
+ its presence using
+
+ .. code-block:: c
+
+ #ifdef LIBGCCJIT_HAVE_global_set_initializer
+
Working with pointers, structs and unions
-----------------------------------------
diff --git a/gcc/jit/jit-playback.h b/gcc/jit/jit-playback.h
index f9b3e675368c..50b69753bb42 100644
--- a/gcc/jit/jit-playback.h
+++ b/gcc/jit/jit-playback.h
@@ -111,6 +111,15 @@ public:
type *type,
const char *name);
+ lvalue *
+ new_global_initialized (location *loc,
+ enum gcc_jit_global_kind kind,
+ type *type,
+ size_t element_size,
+ size_t initializer_num_elem,
+ const void *initializer,
+ const char *name);
+
template <typename HOST_TYPE>
rvalue *
new_rvalue_from_const (type *type,
@@ -266,6 +275,14 @@ private:
const char * get_path_s_file () const;
const char * get_path_so_file () const;
+ tree
+ global_new_decl (location *loc,
+ enum gcc_jit_global_kind kind,
+ type *type,
+ const char *name);
+ lvalue *
+ global_finalize_lvalue (tree inner);
+
private:
/* Functions for implementing "compile". */
diff --git a/gcc/jit/jit-playback.c b/gcc/jit/jit-playback.c
index 0fddf04da873..52fc92f5928c 100644
--- a/gcc/jit/jit-playback.c
+++ b/gcc/jit/jit-playback.c
@@ -510,14 +510,14 @@ new_function (location *loc,
return func;
}
-/* Construct a playback::lvalue instance (wrapping a tree). */
+/* In use by new_global and new_global_initialized. */
-playback::lvalue *
+tree
playback::context::
-new_global (location *loc,
- enum gcc_jit_global_kind kind,
- type *type,
- const char *name)
+global_new_decl (location *loc,
+ enum gcc_jit_global_kind kind,
+ type *type,
+ const char *name)
{
gcc_assert (type);
gcc_assert (name);
@@ -547,6 +547,15 @@ new_global (location *loc,
if (loc)
set_tree_location (inner, loc);
+ return inner;
+}
+
+/* In use by new_global and new_global_initialized. */
+
+playback::lvalue *
+playback::context::
+global_finalize_lvalue (tree inner)
+{
varpool_node::get_create (inner);
varpool_node::finalize_decl (inner);
@@ -556,6 +565,90 @@ new_global (location *loc,
return new lvalue (this, inner);
}
+/* Construct a playback::lvalue instance (wrapping a tree). */
+
+playback::lvalue *
+playback::context::
+new_global (location *loc,
+ enum gcc_jit_global_kind kind,
+ type *type,
+ const char *name)
+{
+ tree inner = global_new_decl (loc, kind, type, name);
+
+ return global_finalize_lvalue (inner);
+}
+
+/* Fill 'constructor_elements' with the memory content of
+ 'initializer'. Each element of the initializer is of the size of
+ type T. In use by new_global_initialized.*/
+
+template<typename T>
+static void
+load_blob_in_ctor (vec<constructor_elt, va_gc> *&constructor_elements,
+ size_t num_elem,
+ const void *initializer)
+{
+ /* Loosely based on 'output_init_element' c-typeck.c:9691. */
+ const T *p = (const T *)initializer;
+ tree node = make_unsigned_type (BITS_PER_UNIT * sizeof (T));
+ for (size_t i = 0; i < num_elem; i++)
+ {
+ constructor_elt celt =
+ { build_int_cst (long_unsigned_type_node, i),
+ build_int_cst (node, p[i]) };
+ vec_safe_push (constructor_elements, celt);
+ }
+}
+
+/* Construct an initialized playback::lvalue instance (wrapping a
+ tree). */
+
+playback::lvalue *
+playback::context::
+new_global_initialized (location *loc,
+ enum gcc_jit_global_kind kind,
+ type *type,
+ size_t element_size,
+ size_t initializer_num_elem,
+ const void *initializer,
+ const char *name)
+{
+ tree inner = global_new_decl (loc, kind, type, name);
+
+ static vec<constructor_elt, va_gc> *constructor_elements;
+
+ switch (element_size)
+ {
+ case 1:
+ load_blob_in_ctor<uint8_t> (constructor_elements, initializer_num_elem,
+ initializer);
+ break;
+ case 2:
+ load_blob_in_ctor<uint16_t> (constructor_elements, initializer_num_elem,
+ initializer);
+ break;
+ case 4:
+ load_blob_in_ctor<uint32_t> (constructor_elements, initializer_num_elem,
+ initializer);
+ break;
+ case 8:
+ load_blob_in_ctor<uint64_t> (constructor_elements, initializer_num_elem,
+ initializer);
+ break;
+ default:
+ gcc_unreachable ();
+ }
+ /* Compare with 'pop_init_level' c-typeck.c:8780. */
+ tree ctor = build_constructor (type->as_tree (), constructor_elements);
+ constructor_elements = NULL;
+
+ /* Compare with 'store_init_value' c-typeck.c:7555. */
+ DECL_INITIAL (inner) = ctor;
+
+ 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-recording.h b/gcc/jit/jit-recording.h
index 726b9c4b8371..7a7a61a0e126 100644
--- a/gcc/jit/jit-recording.h
+++ b/gcc/jit/jit-recording.h
@@ -502,6 +502,7 @@ public:
This will return NULL if it's not valid to dereference this type.
The caller is responsible for setting an error. */
virtual type *dereference () = 0;
+ virtual size_t get_size () { gcc_unreachable (); }
/* Dynamic casts. */
virtual function_type *dyn_cast_function_type () { return NULL; }
@@ -534,6 +535,7 @@ public:
virtual type *is_array () = 0;
virtual bool is_void () const { return false; }
virtual bool has_known_size () const { return true; }
+ virtual int num_elements () { gcc_unreachable (); }
bool is_numeric () const
{
@@ -569,6 +571,8 @@ public:
type *dereference () FINAL OVERRIDE;
+ size_t get_size () FINAL OVERRIDE;
+
bool accepts_writes_from (type *rtype) FINAL OVERRIDE
{
if (m_kind == GCC_JIT_TYPE_VOID_PTR)
@@ -610,6 +614,8 @@ public:
type *dereference () FINAL OVERRIDE { return m_other_type; }
+ size_t get_size () FINAL OVERRIDE;
+
bool accepts_writes_from (type *rtype) FINAL OVERRIDE;
void replay_into (replayer *r) FINAL OVERRIDE;
@@ -755,6 +761,7 @@ class array_type : public type
bool is_bool () const FINAL OVERRIDE { return false; }
type *is_pointer () FINAL OVERRIDE { return NULL; }
type *is_array () FINAL OVERRIDE { return m_element_type; }
+ int num_elements () FINAL OVERRIDE { return m_num_elements; }
void replay_into (replayer *) FINAL OVERRIDE;
@@ -1107,6 +1114,8 @@ public:
const char *access_as_rvalue (reproducer &r) OVERRIDE;
virtual const char *access_as_lvalue (reproducer &r);
+ virtual bool is_global () const { return false; }
+ virtual void set_initializer (const void *, size_t) { gcc_unreachable (); }
};
class param : public lvalue
@@ -1335,8 +1344,23 @@ public:
void write_to_dump (dump &d) FINAL OVERRIDE;
+ virtual bool is_global () const FINAL OVERRIDE { return true; }
+
+ virtual void
+ set_initializer (const void *initializer,
+ size_t num_bytes) FINAL OVERRIDE
+ {
+ if (m_initializer)
+ free (m_initializer);
+ m_initializer = xmalloc (num_bytes);
+ memcpy (m_initializer, initializer, num_bytes);
+ m_initializer_num_bytes = num_bytes;
+ }
+
private:
string * make_debug_string () FINAL OVERRIDE { return m_name; }
+ template <typename T>
+ void write_initializer_reproducer (const char *id, reproducer &r);
void write_reproducer (reproducer &r) FINAL OVERRIDE;
enum precedence get_precedence () const FINAL OVERRIDE
{
@@ -1346,6 +1370,8 @@ private:
private:
enum gcc_jit_global_kind m_kind;
string *m_name;
+ void *m_initializer = NULL;
+ size_t m_initializer_num_bytes = 0;
};
template <typename HOST_TYPE>
diff --git a/gcc/jit/jit-recording.c b/gcc/jit/jit-recording.c
index b73cd76a0a02..f97de00f63c3 100644
--- a/gcc/jit/jit-recording.c
+++ b/gcc/jit/jit-recording.c
@@ -2175,6 +2175,57 @@ recording::type::access_as_type (reproducer &r)
return r.get_identifier (this);
}
+/* Override of default implementation of
+ recording::type::get_size.
+
+ Return the size in bytes. This is in use for global
+ initialization. */
+
+size_t
+recording::memento_of_get_type::get_size ()
+{
+ int size;
+ switch (m_kind)
+ {
+ case GCC_JIT_TYPE_VOID:
+ return 0;
+ case GCC_JIT_TYPE_BOOL:
+ case GCC_JIT_TYPE_CHAR:
+ case GCC_JIT_TYPE_SIGNED_CHAR:
+ case GCC_JIT_TYPE_UNSIGNED_CHAR:
+ return 1;
+ case GCC_JIT_TYPE_SHORT:
+ case GCC_JIT_TYPE_UNSIGNED_SHORT:
+ size = SHORT_TYPE_SIZE;
+ break;
+ case GCC_JIT_TYPE_INT:
+ case GCC_JIT_TYPE_UNSIGNED_INT:
+ size = INT_TYPE_SIZE;
+ break;
+ case GCC_JIT_TYPE_LONG:
+ case GCC_JIT_TYPE_UNSIGNED_LONG:
+ size = LONG_TYPE_SIZE;
+ break;
+ case GCC_JIT_TYPE_LONG_LONG:
+ case GCC_JIT_TYPE_UNSIGNED_LONG_LONG:
+ size = LONG_LONG_TYPE_SIZE;
+ break;
+ case GCC_JIT_TYPE_FLOAT:
+ size = FLOAT_TYPE_SIZE;
+ break;
+ case GCC_JIT_TYPE_DOUBLE:
+ size = DOUBLE_TYPE_SIZE;
+ break;
+ case GCC_JIT_TYPE_LONG_DOUBLE:
+ size = LONG_DOUBLE_TYPE_SIZE;
+ break;
+ default:
+ gcc_unreachable ();
+ }
+
+ return size / BITS_PER_UNIT;
+}
+
/* Implementation of pure virtual hook recording::type::dereference for
recording::memento_of_get_type. */
@@ -2482,6 +2533,15 @@ recording::memento_of_get_type::write_reproducer (reproducer &r)
/* The implementation of class gcc::jit::recording::memento_of_get_pointer. */
+/* Override of default implementation of
+ recording::type::get_size for get_pointer. */
+
+size_t
+recording::memento_of_get_pointer::get_size ()
+{
+ return POINTER_SIZE / BITS_PER_UNIT;
+}
+
/* Override of default implementation of
recording::type::accepts_writes_from for get_pointer.
@@ -4393,10 +4453,20 @@ recording::block::dump_edges_to_dot (pretty_printer *pp)
void
recording::global::replay_into (replayer *r)
{
- set_playback_obj (r->new_global (playback_location (r, m_loc),
- m_kind,
- m_type->playback_type (),
- playback_string (m_name)));
+ set_playback_obj (
+ m_initializer
+ ? 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),
+ m_kind,
+ m_type->playback_type (),
+ playback_string (m_name)));
}
/* Override the default implementation of
@@ -4440,9 +4510,26 @@ recording::global::write_to_dump (dump &d)
d.write ("extern ");
break;
}
- d.write ("%s %s;\n",
+
+ d.write ("%s %s",
m_type->get_debug_string (),
get_debug_string ());
+
+ if (!m_initializer)
+ {
+ d.write (";\n");
+ return;
+ }
+
+ d.write ("=\n { ");
+ const char *p = (const char *)m_initializer;
+ for (size_t i = 0; i < m_initializer_num_bytes; i++)
+ {
+ d.write ("0x%x, ", p[i]);
+ if (i && !(i % 64))
+ d.write ("\n ");
+ }
+ d.write ("};\n");
}
/* A table of enum gcc_jit_global_kind values expressed in string
@@ -4454,6 +4541,27 @@ static const char * const global_kind_reproducer_strings[] = {
"GCC_JIT_GLOBAL_IMPORTED"
};
+template <typename T>
+void
+recording::global::write_initializer_reproducer (const char *id, reproducer &r)
+{
+ const char *init_id = r.make_tmp_identifier ("init_for", this);
+ r.write (" %s %s[] =\n {",
+ m_type->dereference ()->get_debug_string (),
+ init_id);
+
+ const T *p = (const T *)m_initializer;
+ for (size_t i = 0; i < m_initializer_num_bytes / sizeof (T); i++)
+ {
+ r.write ("%lu, ", (uint64_t)p[i]);
+ if (i && !(i % 64))
+ r.write ("\n ");
+ }
+ r.write ("};\n");
+ r.write (" gcc_jit_global_set_initializer (%s, %s, sizeof (%s));\n",
+ id, init_id, init_id);
+}
+
/* Implementation of recording::memento::write_reproducer for globals. */
void
@@ -4472,6 +4580,25 @@ recording::global::write_reproducer (reproducer &r)
global_kind_reproducer_strings[m_kind],
r.get_identifier_as_type (get_type ()),
m_name->get_debug_string ());
+
+ if (m_initializer)
+ switch (m_type->dereference ()->get_size ())
+ {
+ case 1:
+ write_initializer_reproducer<uint8_t> (id, r);
+ break;
+ case 2:
+ write_initializer_reproducer<uint16_t> (id, r);
+ break;
+ case 4:
+ write_initializer_reproducer<uint32_t> (id, r);
+ break;
+ case 8:
+ write_initializer_reproducer<uint64_t> (id, r);
+ break;
+ default:
+ gcc_unreachable ();
+ }
}
/* The implementation of the various const-handling classes:
diff --git a/gcc/jit/libgccjit++.h b/gcc/jit/libgccjit++.h
index 69e67766640c..1b9ef1a5db98 100644
--- a/gcc/jit/libgccjit++.h
+++ b/gcc/jit/libgccjit++.h
@@ -488,6 +488,7 @@ namespace gccjit
location loc = location ());
rvalue get_address (location loc = location ());
+ lvalue set_initializer (const void *blob, size_t num_bytes);
};
class param : public lvalue
@@ -1737,6 +1738,15 @@ lvalue::get_address (location loc)
loc.get_inner_location ()));
}
+inline lvalue
+lvalue::set_initializer (const void *blob, size_t num_bytes)
+{
+ gcc_jit_global_set_initializer (get_inner_lvalue (),
+ blob,
+ num_bytes);
+ return *this;
+}
+
// class param : public lvalue
inline param::param () : lvalue () {}
inline param::param (gcc_jit_param *inner)
diff --git a/gcc/jit/libgccjit.h b/gcc/jit/libgccjit.h
index 1c5a12e9c015..08b855230f6a 100644
--- a/gcc/jit/libgccjit.h
+++ b/gcc/jit/libgccjit.h
@@ -788,6 +788,20 @@ gcc_jit_context_new_global (gcc_jit_context *ctxt,
gcc_jit_type *type,
const char *name);
+#define LIBGCCJIT_HAVE_global_set_initializer
+
+/* Set a static initializer for a global return the global itself.
+
+ This API entrypoint was added in LIBGCCJIT_ABI_14; you can test for its
+ presence using
+ #ifdef LIBGCCJIT_HAVE_gcc_jit_global_set_initializer
+*/
+
+extern gcc_jit_lvalue *
+gcc_jit_global_set_initializer (gcc_jit_lvalue *global,
+ const void *blob,
+ size_t num_bytes);
+
/* Upcasting. */
extern gcc_jit_object *
gcc_jit_lvalue_as_object (gcc_jit_lvalue *lvalue);
diff --git a/gcc/jit/libgccjit.c b/gcc/jit/libgccjit.c
index 3d04f6db3aff..80c5aa6ac115 100644
--- a/gcc/jit/libgccjit.c
+++ b/gcc/jit/libgccjit.c
@@ -1117,6 +1117,42 @@ gcc_jit_context_new_global (gcc_jit_context *ctxt,
return (gcc_jit_lvalue *)ctxt->new_global (loc, kind, type, name);
}
+/* Public entrypoint. See description in libgccjit.h.
+
+ After error-checking, the real work is done by the
+ gcc::jit::recording::global::set_initializer method, in
+ jit-recording.c. */
+
+extern gcc_jit_lvalue *
+gcc_jit_global_set_initializer (gcc_jit_lvalue *global,
+ const void *blob,
+ size_t num_bytes)
+{
+ RETURN_NULL_IF_FAIL (global, NULL, NULL, "NULL global");
+ RETURN_NULL_IF_FAIL (blob, NULL, NULL, "NULL blob");
+ RETURN_NULL_IF_FAIL_PRINTF1 (global->is_global (), NULL, NULL,
+ "global \"%s\" not a global",
+ global->get_debug_string ());
+
+ gcc::jit::recording::type *lval_type = global->get_type ();
+ RETURN_NULL_IF_FAIL_PRINTF1 (lval_type->is_array (), NULL, NULL,
+ "global \"%s\" not an array",
+ global->get_debug_string ());
+ RETURN_NULL_IF_FAIL_PRINTF1 (lval_type->dereference ()->is_int (), NULL, NULL,
+ "global \"%s\" not an array of integral type",
+ global->get_debug_string ());
+ RETURN_NULL_IF_FAIL_PRINTF1 (
+ lval_type->dereference ()->get_size() * lval_type->num_elements ()
+ == num_bytes,
+ NULL, NULL,
+ "global \"%s\" and initializer don't match size",
+ global->get_debug_string ());
+
+ global->set_initializer (blob, num_bytes);
+
+ return global;
+}
+
/* Public entrypoint. See description in libgccjit.h.
After error-checking, this calls the trivial
diff --git a/gcc/jit/libgccjit.map b/gcc/jit/libgccjit.map
index 6137dd4b4b03..a6e67e781a4b 100644
--- a/gcc/jit/libgccjit.map
+++ b/gcc/jit/libgccjit.map
@@ -186,4 +186,9 @@ LIBGCCJIT_ABI_13 {
gcc_jit_version_major;
gcc_jit_version_minor;
gcc_jit_version_patchlevel;
-} LIBGCCJIT_ABI_12;
\ No newline at end of file
+} LIBGCCJIT_ABI_12;
+
+LIBGCCJIT_ABI_14 {
+ global:
+ gcc_jit_global_set_initializer;
+} LIBGCCJIT_ABI_13;
diff --git a/gcc/testsuite/jit.dg/all-non-failing-tests.h b/gcc/testsuite/jit.dg/all-non-failing-tests.h
index 632ab8cfb2e4..4202eb7798b7 100644
--- a/gcc/testsuite/jit.dg/all-non-failing-tests.h
+++ b/gcc/testsuite/jit.dg/all-non-failing-tests.h
@@ -174,6 +174,13 @@
#undef create_code
#undef verify_code
+/* test-global-set-initializer.c */
+#define create_code create_code_global_set_initializer
+#define verify_code verify_code_global_set_initializer
+#include "test-global-set-initializer.c"
+#undef create_code
+#undef verify_code
+
/* test-hello-world.c */
#define create_code create_code_hello_world
#define verify_code verify_code_hello_world
diff --git a/gcc/testsuite/jit.dg/test-global-set-initializer.c b/gcc/testsuite/jit.dg/test-global-set-initializer.c
new file mode 100644
index 000000000000..d38aba7d73f5
--- /dev/null
+++ b/gcc/testsuite/jit.dg/test-global-set-initializer.c
@@ -0,0 +1,78 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <time.h>
+
+#include "libgccjit.h"
+
+#include "harness.h"
+
+#define BIG_BLOB_SIZE (1 << 12) /* 4KB. */
+
+static signed char test_blob1[] = { 0xc, 0xa, 0xf, 0xf, 0xe };
+static unsigned test_blob2[] = { 0x3, 0x2, 0x1, 0x0, 0x1, 0x2, 0x3 };
+static unsigned char test_blob3[BIG_BLOB_SIZE];
+
+void
+create_code (gcc_jit_context *ctxt, void *user_data)
+{
+ /* Let's try to inject the equivalent of:
+
+ signed char bin_blob1[] = { 0xc, 0xa, 0xf, 0xf, 0xe };
+ unsigned bin_blob2[] = { 0x3, 0x2, 0x1, 0x0, 0x1, 0x2, 0x3 };
+ unsigned char bin_blob3[4096]...
+ */
+ gcc_jit_type *unsigned_char_type =
+ gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_UNSIGNED_CHAR);
+ gcc_jit_type *signed_char_type =
+ gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_SIGNED_CHAR);
+ gcc_jit_type *unsigned_type =
+ gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_UNSIGNED_INT);
+
+ gcc_jit_lvalue *glob =
+ gcc_jit_context_new_global (
+ ctxt, NULL, GCC_JIT_GLOBAL_EXPORTED,
+ gcc_jit_context_new_array_type (ctxt, NULL, signed_char_type,
+ sizeof (test_blob1)),
+ "bin_blob1");
+ gcc_jit_global_set_initializer (glob, test_blob1, sizeof (test_blob1));
+
+ glob =
+ gcc_jit_context_new_global (
+ ctxt, NULL, GCC_JIT_GLOBAL_EXPORTED,
+ gcc_jit_context_new_array_type (
+ ctxt, NULL, unsigned_type,
+ sizeof (test_blob2) / sizeof (*test_blob2)),
+ "bin_blob2");
+ gcc_jit_global_set_initializer (glob, test_blob2,
+ sizeof (test_blob2));
+
+ for (size_t i = 0; i < BIG_BLOB_SIZE; i++)
+ test_blob3[i] = i * i + i;
+ glob =
+ gcc_jit_context_new_global (
+ ctxt, NULL, GCC_JIT_GLOBAL_EXPORTED,
+ gcc_jit_context_new_array_type (ctxt, NULL, unsigned_char_type,
+ sizeof (test_blob3)),
+ "bin_blob3");
+ gcc_jit_global_set_initializer (glob, test_blob3, sizeof (test_blob3));
+}
+
+void
+verify_code (gcc_jit_context *ctxt, gcc_jit_result *result)
+{
+ CHECK_NON_NULL (result);
+ void *glob = gcc_jit_result_get_global (result, "bin_blob1");
+ CHECK_NON_NULL (glob);
+ CHECK_VALUE (memcmp (test_blob1, glob, sizeof (test_blob1)), 0);
+
+ glob = gcc_jit_result_get_global (result, "bin_blob2");
+ CHECK_NON_NULL (glob);
+ CHECK_VALUE (memcmp (test_blob2, glob,
+ sizeof (test_blob2)), 0);
+
+ glob = gcc_jit_result_get_global (result, "bin_blob3");
+ CHECK_NON_NULL (glob);
+ CHECK_VALUE (memcmp (test_blob3, glob, sizeof (test_blob3)), 0);
+
+}
--
2.17.1
next prev parent reply other threads:[~2020-08-03 8:08 UTC|newest]
Thread overview: 14+ messages / expand[flat|nested] mbox.gz Atom feed top
2020-06-03 10:11 Andrea Corallo
2020-06-03 15:03 ` David Malcolm
2020-06-03 16:36 ` Andrea Corallo
2020-07-01 16:14 ` Andrea Corallo
2020-07-14 10:00 ` Andrea Corallo
2020-07-24 22:05 ` David Malcolm
2020-07-24 22:12 ` David Malcolm
2020-08-03 8:07 ` Andrea Corallo [this message]
2020-08-06 19:53 ` David Malcolm
2020-08-19 7:17 ` [PATCH V2] " Andrea Corallo
2020-09-09 7:51 ` Andrea Corallo
2020-09-10 22:22 ` David Malcolm
2020-09-11 10:31 ` Andrea Corallo
2020-09-11 11:27 ` David Malcolm
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=gkr3654f8yu.fsf@arm.com \
--to=andrea.corallo@arm.com \
--cc=dmalcolm@redhat.com \
--cc=gcc-patches@gcc.gnu.org \
--cc=jit@gcc.gnu.org \
--cc=nd@arm.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
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).