* [PATCH] libgccjit: Add support for bitcasts [PR104071]
@ 2022-01-17 22:18 Antoni Boucher
2022-01-18 0:30 ` Antoni Boucher
0 siblings, 1 reply; 7+ messages in thread
From: Antoni Boucher @ 2022-01-17 22:18 UTC (permalink / raw)
To: gcc-patches, jit
[-- Attachment #1: Type: text/plain, Size: 587 bytes --]
Hi.
This patch add support for bitcasts in libgccjit.
It passes the JIT tests, but since I added a function in tree.c, I
wonder if I should run the whole testsuite.
David, you can now disregard my question in my email about 128-bit
integers regarding my issue with initialize_sizetypes being called
multiple times because this patch fix this issue.
I turns out there was a cache of types that needed to be cleared when
you initialize the JIT.
The check for sizes is pending, because it requires the updates to
get_size I made in my patch for 128-bit integers.
Thanks for the review!
[-- Attachment #2: 0001-libgccjit-Add-support-for-bitcasts-PR104071.patch --]
[-- Type: text/x-patch, Size: 15515 bytes --]
From 35e113b51c416af0c13bc7eb160ff6c0cbcff813 Mon Sep 17 00:00:00 2001
From: Antoni Boucher <bouanto@zoho.com>
Date: Wed, 9 Jun 2021 18:29:14 -0400
Subject: [PATCH] libgccjit: Add support for bitcasts [PR104071]
2022-01-17 Antoni Boucher <bouanto@zoho.com>
gcc/jit/
PR target/104071
* docs/topics/compatibility.rst (LIBGCCJIT_ABI_20): New ABI tag.
* docs/topics/expressions.rst: Add documentation for the
function gcc_jit_context_new_bitcast.
* dummy-frontend.c: clear the cache of non-standard integer
types to avoid having issues with some optimizations of
bitcast where the SSA_NAME will have a size of a cached
integer type that should have been invalidated, causing a
comparison of integer constant to fail.
* jit-playback.c: New function (new_bitcast).
* jit-playback.h: New function (new_bitcast).
* jit-recording.c: New functions (new_bitcast,
bitcast::replay_into, bitcast::visit_children,
bitcast::make_debug_string, bitcast::write_reproducer).
* jit-recording.h: New calss (bitcast) and new function
(new_bitcast, bitcast::replay_into, bitcast::visit_children,
bitcast::make_debug_string, bitcast::write_reproducer,
bitcast::get_precedence).
* libgccjit.c: New function (gcc_jit_context_new_bitcast)
* libgccjit.h: New function (gcc_jit_context_new_bitcast)
* libgccjit.map (LIBGCCJIT_ABI_20): New ABI tag.
gcc/testsuite/
PR target/104071
* jit.dg/all-non-failing-tests.h: Add new test-bitcast.
* jit.dg/test-bitcast.c: New test.
gcc/
PR target/104071
* tree.c: New function (clear_nonstandard_integer_type_cache).
* tree.h: New function (clear_nonstandard_integer_type_cache).
---
gcc/jit/docs/topics/compatibility.rst | 9 +++
gcc/jit/docs/topics/expressions.rst | 10 +++
gcc/jit/dummy-frontend.c | 2 +
gcc/jit/jit-playback.c | 13 ++++
gcc/jit/jit-playback.h | 5 ++
gcc/jit/jit-recording.c | 66 ++++++++++++++++++++
gcc/jit/jit-recording.h | 32 ++++++++++
gcc/jit/libgccjit.c | 28 +++++++++
gcc/jit/libgccjit.h | 9 +++
gcc/jit/libgccjit.map | 6 ++
gcc/testsuite/jit.dg/all-non-failing-tests.h | 10 +++
gcc/testsuite/jit.dg/test-bitcast.c | 60 ++++++++++++++++++
gcc/tree.c | 8 +++
gcc/tree.h | 1 +
14 files changed, 259 insertions(+)
create mode 100644 gcc/testsuite/jit.dg/test-bitcast.c
diff --git a/gcc/jit/docs/topics/compatibility.rst b/gcc/jit/docs/topics/compatibility.rst
index 16cebe31a10..b5a6b704dda 100644
--- a/gcc/jit/docs/topics/compatibility.rst
+++ b/gcc/jit/docs/topics/compatibility.rst
@@ -302,3 +302,12 @@ thread-local storage model of a variable:
section of a variable:
* :func:`gcc_jit_lvalue_set_link_section`
+
+.. _LIBGCCJIT_ABI_20:
+
+``LIBGCCJIT_ABI_20``
+-----------------------
+``LIBGCCJIT_ABI_20`` covers the addition of an API entrypoint to bitcast a
+value from one type to another:
+
+ * :func:`gcc_jit_context_new_bitcast`
diff --git a/gcc/jit/docs/topics/expressions.rst b/gcc/jit/docs/topics/expressions.rst
index 791a20398ca..6e0b5db777b 100644
--- a/gcc/jit/docs/topics/expressions.rst
+++ b/gcc/jit/docs/topics/expressions.rst
@@ -649,6 +649,16 @@ Type-coercion
* int <-> bool
* P* <-> Q*, for pointer types P and Q
+.. function:: gcc_jit_rvalue *\
+ gcc_jit_context_new_bitcast (gcc_jit_context *ctxt,\
+ gcc_jit_location *loc,\
+ gcc_jit_rvalue *rvalue,\
+ gcc_jit_type *type)
+
+ Given an rvalue of T, bitcast it to another type.
+
+ The type of rvalue must be the same size as the size of ``type``.
+
Lvalues
-------
diff --git a/gcc/jit/dummy-frontend.c b/gcc/jit/dummy-frontend.c
index 84ff359bfe3..c3da97642e3 100644
--- a/gcc/jit/dummy-frontend.c
+++ b/gcc/jit/dummy-frontend.c
@@ -592,6 +592,8 @@ jit_langhook_init (void)
global_dc->begin_diagnostic = jit_begin_diagnostic;
global_dc->end_diagnostic = jit_end_diagnostic;
+ clear_nonstandard_integer_type_cache ();
+
build_common_tree_nodes (false);
/* I don't know why this has to be done explicitly. */
diff --git a/gcc/jit/jit-playback.c b/gcc/jit/jit-playback.c
index 1d64caf4e20..4ad2f6ce41d 100644
--- a/gcc/jit/jit-playback.c
+++ b/gcc/jit/jit-playback.c
@@ -1390,6 +1390,19 @@ new_cast (playback::location *loc,
return new rvalue (this, t_cast);
}
+playback::rvalue *
+playback::context::
+new_bitcast (location *loc,
+ rvalue *expr,
+ type *type_)
+{
+ tree t_bitcast = build1 (VIEW_CONVERT_EXPR,
+ type_->as_tree (), expr->as_tree ());
+ if (loc)
+ set_tree_location (t_bitcast, loc);
+ return new rvalue (this, t_bitcast);
+}
+
/* Construct a playback::lvalue instance (wrapping a tree) for an
array access. */
diff --git a/gcc/jit/jit-playback.h b/gcc/jit/jit-playback.h
index c93d7055d43..5b107be9d69 100644
--- a/gcc/jit/jit-playback.h
+++ b/gcc/jit/jit-playback.h
@@ -180,6 +180,11 @@ public:
rvalue *expr,
type *type_);
+ rvalue *
+ new_bitcast (location *loc,
+ rvalue *expr,
+ type *type_);
+
lvalue *
new_array_access (location *loc,
rvalue *ptr,
diff --git a/gcc/jit/jit-recording.c b/gcc/jit/jit-recording.c
index ee8934131d1..ae3381b586d 100644
--- a/gcc/jit/jit-recording.c
+++ b/gcc/jit/jit-recording.c
@@ -1242,6 +1242,22 @@ recording::context::new_cast (recording::location *loc,
return result;
}
+/* Create a recording::bitcast instance and add it to this context's list
+ of mementos.
+
+ Implements the post-error-checking part of
+ gcc_jit_context_new_bitcast. */
+
+recording::rvalue *
+recording::context::new_bitcast (location *loc,
+ rvalue *expr,
+ type *type_)
+{
+ recording::rvalue *result = new bitcast (this, loc, expr, type_);
+ record (result);
+ return result;
+}
+
/* Create a recording::call instance and add it to this context's list
of mementos.
@@ -5740,6 +5756,56 @@ recording::cast::write_reproducer (reproducer &r)
r.get_identifier_as_type (get_type ()));
}
+/* Implementation of pure virtual hook recording::memento::replay_into
+ for recording::bitcast. */
+
+void
+recording::bitcast::replay_into (replayer *r)
+{
+ set_playback_obj (r->new_bitcast (playback_location (r, m_loc),
+ m_rvalue->playback_rvalue (),
+ get_type ()->playback_type ()));
+}
+
+/* Implementation of pure virtual hook recording::rvalue::visit_children
+ for recording::bitcast. */
+void
+recording::bitcast::visit_children (rvalue_visitor *v)
+{
+ v->visit (m_rvalue);
+}
+
+/* Implementation of recording::memento::make_debug_string for
+ casts. */
+
+recording::string *
+recording::bitcast::make_debug_string ()
+{
+ enum precedence prec = get_precedence ();
+ return string::from_printf (m_ctxt,
+ "bitcast(%s, %s)",
+ m_rvalue->get_debug_string_parens (prec),
+ get_type ()->get_debug_string ());
+}
+
+/* Implementation of recording::memento::write_reproducer for casts. */
+
+void
+recording::bitcast::write_reproducer (reproducer &r)
+{
+ const char *id = r.make_identifier (this, "rvalue");
+ r.write (" gcc_jit_rvalue *%s =\n"
+ " gcc_jit_context_new_bitcast (%s,\n"
+ " %s, /* gcc_jit_location *loc */\n"
+ " %s, /* gcc_jit_rvalue *rvalue */\n"
+ " %s); /* gcc_jit_type *type */\n",
+ id,
+ r.get_identifier (get_context ()),
+ r.get_identifier (m_loc),
+ r.get_identifier_as_rvalue (m_rvalue),
+ r.get_identifier_as_type (get_type ()));
+}
+
/* The implementation of class gcc::jit::recording::base_call. */
/* The constructor for gcc::jit::recording::base_call. */
diff --git a/gcc/jit/jit-recording.h b/gcc/jit/jit-recording.h
index b663d0f21f5..713aac36ebe 100644
--- a/gcc/jit/jit-recording.h
+++ b/gcc/jit/jit-recording.h
@@ -205,6 +205,11 @@ public:
rvalue *expr,
type *type_);
+ rvalue *
+ new_bitcast (location *loc,
+ rvalue *expr,
+ type *type_);
+
lvalue *
new_array_access (location *loc,
rvalue *ptr,
@@ -1691,6 +1696,33 @@ private:
rvalue *m_rvalue;
};
+class bitcast : public rvalue
+{
+public:
+ bitcast (context *ctxt,
+ location *loc,
+ rvalue *a,
+ type *type_)
+ : rvalue (ctxt, loc, type_),
+ m_rvalue (a)
+ {}
+
+ void replay_into (replayer *r) FINAL OVERRIDE;
+
+ void visit_children (rvalue_visitor *v) FINAL OVERRIDE;
+
+private:
+ string * make_debug_string () FINAL OVERRIDE;
+ void write_reproducer (reproducer &r) FINAL OVERRIDE;
+ enum precedence get_precedence () const FINAL OVERRIDE
+ {
+ return PRECEDENCE_CAST;
+ }
+
+private:
+ rvalue *m_rvalue;
+};
+
class base_call : public rvalue
{
public:
diff --git a/gcc/jit/libgccjit.c b/gcc/jit/libgccjit.c
index 03704ef10b8..cd8516d1c4d 100644
--- a/gcc/jit/libgccjit.c
+++ b/gcc/jit/libgccjit.c
@@ -2405,6 +2405,34 @@ gcc_jit_context_new_cast (gcc_jit_context *ctxt,
return static_cast <gcc_jit_rvalue *> (ctxt->new_cast (loc, rvalue, type));
}
+/* Public entrypoint. See description in libgccjit.h.
+
+ After error-checking, the real work is done by the
+ gcc::jit::recording::context::new_bitcast method in jit-recording.c. */
+
+gcc_jit_rvalue *
+gcc_jit_context_new_bitcast (gcc_jit_context *ctxt,
+ gcc_jit_location *loc,
+ gcc_jit_rvalue *rvalue,
+ gcc_jit_type *type)
+{
+ RETURN_NULL_IF_FAIL (ctxt, NULL, loc, "NULL context");
+ JIT_LOG_FUNC (ctxt->get_logger ());
+ /* LOC can be NULL. */
+ RETURN_NULL_IF_FAIL (rvalue, ctxt, loc, "NULL rvalue");
+ RETURN_NULL_IF_FAIL (type, ctxt, loc, "NULL type");
+ // TODO: check the sizes.
+ /*RETURN_NULL_IF_FAIL_PRINTF3 (
+ is_valid_cast (rvalue->get_type (), type),
+ ctxt, loc,
+ "cannot cast %s from type: %s to type: %s",
+ rvalue->get_debug_string (),
+ rvalue->get_type ()->get_debug_string (),
+ type->get_debug_string ());*/
+
+ return static_cast <gcc_jit_rvalue *> (ctxt->new_bitcast (loc, rvalue, type));
+}
+
/* Public entrypoint. See description in libgccjit.h.
After error-checking, the real work is done by the
diff --git a/gcc/jit/libgccjit.h b/gcc/jit/libgccjit.h
index 2a5ffacb1fe..de4f9daaebc 100644
--- a/gcc/jit/libgccjit.h
+++ b/gcc/jit/libgccjit.h
@@ -1206,6 +1206,15 @@ gcc_jit_context_new_cast (gcc_jit_context *ctxt,
gcc_jit_rvalue *rvalue,
gcc_jit_type *type);
+/* Reinterpret a value as another type.
+
+ The types must be of the same size. */
+extern gcc_jit_rvalue *
+gcc_jit_context_new_bitcast (gcc_jit_context *ctxt,
+ gcc_jit_location *loc,
+ gcc_jit_rvalue *rvalue,
+ gcc_jit_type *type);
+
extern gcc_jit_lvalue *
gcc_jit_context_new_array_access (gcc_jit_context *ctxt,
gcc_jit_location *loc,
diff --git a/gcc/jit/libgccjit.map b/gcc/jit/libgccjit.map
index f373fd39ac7..7b6f415ac82 100644
--- a/gcc/jit/libgccjit.map
+++ b/gcc/jit/libgccjit.map
@@ -238,8 +238,14 @@ LIBGCCJIT_ABI_18 {
} LIBGCCJIT_ABI_17;
LIBGCCJIT_ABI_19 {
+ global:
gcc_jit_context_new_array_constructor;
gcc_jit_context_new_struct_constructor;
gcc_jit_context_new_union_constructor;
gcc_jit_global_set_initializer_rvalue;
} LIBGCCJIT_ABI_18;
+
+LIBGCCJIT_ABI_20 {
+ global:
+ gcc_jit_context_new_bitcast;
+} LIBGCCJIT_ABI_19;
diff --git a/gcc/testsuite/jit.dg/all-non-failing-tests.h b/gcc/testsuite/jit.dg/all-non-failing-tests.h
index 29afe064db6..656351edce1 100644
--- a/gcc/testsuite/jit.dg/all-non-failing-tests.h
+++ b/gcc/testsuite/jit.dg/all-non-failing-tests.h
@@ -77,6 +77,13 @@
/* test-builtin-unreachable.c: We don't add this one, since it touches
the optimization level of the context as a whole. */
+/* test-bitcast.c */
+#define create_code create_code_bitcast
+#define verify_code verify_code_bitcast
+#include "test-bitcast.c"
+#undef create_code
+#undef verify_code
+
/* test-calling-external-function.c */
#define create_code create_code_calling_external_function
#define verify_code verify_code_calling_external_function
@@ -400,6 +407,9 @@ const struct testcase testcases[] = {
{"builtin-memcpy",
create_code_builtin_memcpy,
verify_code_builtin_memcpy},
+ {"bitcast",
+ create_code_bitcast,
+ verify_code_bitcast},
{"calling_external_function",
create_code_calling_external_function,
verify_code_calling_external_function},
diff --git a/gcc/testsuite/jit.dg/test-bitcast.c b/gcc/testsuite/jit.dg/test-bitcast.c
new file mode 100644
index 00000000000..2d70622051a
--- /dev/null
+++ b/gcc/testsuite/jit.dg/test-bitcast.c
@@ -0,0 +1,60 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.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:
+int
+my_bitcast (double x)
+{
+ return bitcast(x, int);
+}
+ */
+ gcc_jit_type *int_type =
+ gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_INT);
+ gcc_jit_type *double_type =
+ gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_FLOAT);
+
+ gcc_jit_param *x =
+ gcc_jit_context_new_param (
+ ctxt,
+ NULL,
+ double_type, "x");
+ gcc_jit_param *params[1] = {x};
+ gcc_jit_function *func =
+ gcc_jit_context_new_function (ctxt,
+ NULL,
+ GCC_JIT_FUNCTION_EXPORTED,
+ int_type,
+ "my_bitcast",
+ 1, params, 0);
+
+ gcc_jit_block *initial =
+ gcc_jit_function_new_block (func, "initial");
+
+ gcc_jit_block_end_with_return(initial, NULL,
+ gcc_jit_context_new_bitcast(ctxt,
+ NULL,
+ gcc_jit_param_as_rvalue(x),
+ int_type
+ ));
+}
+
+void
+verify_code (gcc_jit_context *ctxt, gcc_jit_result *result)
+{
+ typedef int (*my_bitcast_fn_type) (double);
+ CHECK_NON_NULL (result);
+ my_bitcast_fn_type my_bitcast =
+ (my_bitcast_fn_type)gcc_jit_result_get_code (result, "my_bitcast");
+ CHECK_NON_NULL (my_bitcast);
+ int val = my_bitcast (-5.1298714);
+ note ("my_bitcast returned: %d", val);
+ CHECK_VALUE (val, 35569201);
+}
diff --git a/gcc/tree.c b/gcc/tree.c
index d98b77db50b..e4bf4e84675 100644
--- a/gcc/tree.c
+++ b/gcc/tree.c
@@ -6963,6 +6963,14 @@ build_reference_type (tree to_type)
(HOST_BITS_PER_WIDE_INT > 64 ? HOST_BITS_PER_WIDE_INT : 64)
static GTY(()) tree nonstandard_integer_type_cache[2 * MAX_INT_CACHED_PREC + 2];
+void clear_nonstandard_integer_type_cache (void)
+{
+ for (size_t i = 0 ; i < 2 * MAX_INT_CACHED_PREC + 2 ; i++)
+ {
+ nonstandard_integer_type_cache[i] = NULL;
+ }
+}
+
/* Builds a signed or unsigned integer type of precision PRECISION.
Used for C bitfields whose precision does not match that of
built-in target types. */
diff --git a/gcc/tree.h b/gcc/tree.h
index 318019c4dc5..640b492802c 100644
--- a/gcc/tree.h
+++ b/gcc/tree.h
@@ -5385,6 +5385,7 @@ extern bool real_minus_onep (const_tree);
extern void init_ttree (void);
extern void build_common_tree_nodes (bool);
extern void build_common_builtin_nodes (void);
+extern void clear_nonstandard_integer_type_cache (void);
extern tree build_nonstandard_integer_type (unsigned HOST_WIDE_INT, int);
extern tree build_nonstandard_boolean_type (unsigned HOST_WIDE_INT);
extern tree build_range_type (tree, tree, tree);
--
2.26.2.7.g19db9cfb68.dirty
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH] libgccjit: Add support for bitcasts [PR104071]
2022-01-17 22:18 [PATCH] libgccjit: Add support for bitcasts [PR104071] Antoni Boucher
@ 2022-01-18 0:30 ` Antoni Boucher
2022-01-18 23:06 ` David Malcolm
0 siblings, 1 reply; 7+ messages in thread
From: Antoni Boucher @ 2022-01-18 0:30 UTC (permalink / raw)
To: gcc-patches, jit
[-- Attachment #1: Type: text/plain, Size: 790 bytes --]
I was missing the define, so I added it.
Here's the new patch with it.
Le lundi 17 janvier 2022 à 17:18 -0500, Antoni Boucher via Jit a
écrit :
> Hi.
> This patch add support for bitcasts in libgccjit.
>
> It passes the JIT tests, but since I added a function in tree.c, I
> wonder if I should run the whole testsuite.
>
> David, you can now disregard my question in my email about 128-bit
> integers regarding my issue with initialize_sizetypes being called
> multiple times because this patch fix this issue.
> I turns out there was a cache of types that needed to be cleared when
> you initialize the JIT.
>
> The check for sizes is pending, because it requires the updates to
> get_size I made in my patch for 128-bit integers.
>
> Thanks for the review!
[-- Attachment #2: 0001-libgccjit-Add-support-for-bitcasts-PR104071.patch --]
[-- Type: text/x-patch, Size: 15909 bytes --]
From 8457f791b08feb0372a76d6a076cc976b59e8e24 Mon Sep 17 00:00:00 2001
From: Antoni Boucher <bouanto@zoho.com>
Date: Wed, 9 Jun 2021 18:29:14 -0400
Subject: [PATCH] libgccjit: Add support for bitcasts [PR104071]
2022-01-17 Antoni Boucher <bouanto@zoho.com>
gcc/jit/
PR target/104071
* docs/topics/compatibility.rst (LIBGCCJIT_ABI_20): New ABI tag.
* docs/topics/expressions.rst: Add documentation for the
function gcc_jit_context_new_bitcast.
* dummy-frontend.c: clear the cache of non-standard integer
types to avoid having issues with some optimizations of
bitcast where the SSA_NAME will have a size of a cached
integer type that should have been invalidated, causing a
comparison of integer constant to fail.
* jit-playback.c: New function (new_bitcast).
* jit-playback.h: New function (new_bitcast).
* jit-recording.c: New functions (new_bitcast,
bitcast::replay_into, bitcast::visit_children,
bitcast::make_debug_string, bitcast::write_reproducer).
* jit-recording.h: New calss (bitcast) and new function
(new_bitcast, bitcast::replay_into, bitcast::visit_children,
bitcast::make_debug_string, bitcast::write_reproducer,
bitcast::get_precedence).
* libgccjit.c: New function (gcc_jit_context_new_bitcast)
* libgccjit.h: New function (gcc_jit_context_new_bitcast)
* libgccjit.map (LIBGCCJIT_ABI_20): New ABI tag.
gcc/testsuite/
PR target/104071
* jit.dg/all-non-failing-tests.h: Add new test-bitcast.
* jit.dg/test-bitcast.c: New test.
gcc/
PR target/104071
* tree.c: New function (clear_nonstandard_integer_type_cache).
* tree.h: New function (clear_nonstandard_integer_type_cache).
---
gcc/jit/docs/topics/compatibility.rst | 9 +++
gcc/jit/docs/topics/expressions.rst | 17 +++++
gcc/jit/dummy-frontend.c | 2 +
gcc/jit/jit-playback.c | 13 ++++
gcc/jit/jit-playback.h | 5 ++
gcc/jit/jit-recording.c | 66 ++++++++++++++++++++
gcc/jit/jit-recording.h | 32 ++++++++++
gcc/jit/libgccjit.c | 28 +++++++++
gcc/jit/libgccjit.h | 15 +++++
gcc/jit/libgccjit.map | 6 ++
gcc/testsuite/jit.dg/all-non-failing-tests.h | 10 +++
gcc/testsuite/jit.dg/test-bitcast.c | 60 ++++++++++++++++++
gcc/tree.c | 8 +++
gcc/tree.h | 1 +
14 files changed, 272 insertions(+)
create mode 100644 gcc/testsuite/jit.dg/test-bitcast.c
diff --git a/gcc/jit/docs/topics/compatibility.rst b/gcc/jit/docs/topics/compatibility.rst
index 16cebe31a10..b5a6b704dda 100644
--- a/gcc/jit/docs/topics/compatibility.rst
+++ b/gcc/jit/docs/topics/compatibility.rst
@@ -302,3 +302,12 @@ thread-local storage model of a variable:
section of a variable:
* :func:`gcc_jit_lvalue_set_link_section`
+
+.. _LIBGCCJIT_ABI_20:
+
+``LIBGCCJIT_ABI_20``
+-----------------------
+``LIBGCCJIT_ABI_20`` covers the addition of an API entrypoint to bitcast a
+value from one type to another:
+
+ * :func:`gcc_jit_context_new_bitcast`
diff --git a/gcc/jit/docs/topics/expressions.rst b/gcc/jit/docs/topics/expressions.rst
index 791a20398ca..1328a53f70f 100644
--- a/gcc/jit/docs/topics/expressions.rst
+++ b/gcc/jit/docs/topics/expressions.rst
@@ -649,6 +649,23 @@ Type-coercion
* int <-> bool
* P* <-> Q*, for pointer types P and Q
+.. function:: gcc_jit_rvalue *\
+ gcc_jit_context_new_bitcast (gcc_jit_context *ctxt,\
+ gcc_jit_location *loc,\
+ gcc_jit_rvalue *rvalue,\
+ gcc_jit_type *type)
+
+ Given an rvalue of T, bitcast it to another type.
+
+ The type of rvalue must be the same size as the size of ``type``.
+
+ This entrypoint was added in :ref:`LIBGCCJIT_ABI_20`; you can test for
+ its presence using
+
+ .. code-block:: c
+
+ #ifdef LIBGCCJIT_HAVE_gcc_jit_context_new_bitcast
+
Lvalues
-------
diff --git a/gcc/jit/dummy-frontend.c b/gcc/jit/dummy-frontend.c
index 84ff359bfe3..c3da97642e3 100644
--- a/gcc/jit/dummy-frontend.c
+++ b/gcc/jit/dummy-frontend.c
@@ -592,6 +592,8 @@ jit_langhook_init (void)
global_dc->begin_diagnostic = jit_begin_diagnostic;
global_dc->end_diagnostic = jit_end_diagnostic;
+ clear_nonstandard_integer_type_cache ();
+
build_common_tree_nodes (false);
/* I don't know why this has to be done explicitly. */
diff --git a/gcc/jit/jit-playback.c b/gcc/jit/jit-playback.c
index 1d64caf4e20..4ad2f6ce41d 100644
--- a/gcc/jit/jit-playback.c
+++ b/gcc/jit/jit-playback.c
@@ -1390,6 +1390,19 @@ new_cast (playback::location *loc,
return new rvalue (this, t_cast);
}
+playback::rvalue *
+playback::context::
+new_bitcast (location *loc,
+ rvalue *expr,
+ type *type_)
+{
+ tree t_bitcast = build1 (VIEW_CONVERT_EXPR,
+ type_->as_tree (), expr->as_tree ());
+ if (loc)
+ set_tree_location (t_bitcast, loc);
+ return new rvalue (this, t_bitcast);
+}
+
/* Construct a playback::lvalue instance (wrapping a tree) for an
array access. */
diff --git a/gcc/jit/jit-playback.h b/gcc/jit/jit-playback.h
index c93d7055d43..5b107be9d69 100644
--- a/gcc/jit/jit-playback.h
+++ b/gcc/jit/jit-playback.h
@@ -180,6 +180,11 @@ public:
rvalue *expr,
type *type_);
+ rvalue *
+ new_bitcast (location *loc,
+ rvalue *expr,
+ type *type_);
+
lvalue *
new_array_access (location *loc,
rvalue *ptr,
diff --git a/gcc/jit/jit-recording.c b/gcc/jit/jit-recording.c
index ee8934131d1..ae3381b586d 100644
--- a/gcc/jit/jit-recording.c
+++ b/gcc/jit/jit-recording.c
@@ -1242,6 +1242,22 @@ recording::context::new_cast (recording::location *loc,
return result;
}
+/* Create a recording::bitcast instance and add it to this context's list
+ of mementos.
+
+ Implements the post-error-checking part of
+ gcc_jit_context_new_bitcast. */
+
+recording::rvalue *
+recording::context::new_bitcast (location *loc,
+ rvalue *expr,
+ type *type_)
+{
+ recording::rvalue *result = new bitcast (this, loc, expr, type_);
+ record (result);
+ return result;
+}
+
/* Create a recording::call instance and add it to this context's list
of mementos.
@@ -5740,6 +5756,56 @@ recording::cast::write_reproducer (reproducer &r)
r.get_identifier_as_type (get_type ()));
}
+/* Implementation of pure virtual hook recording::memento::replay_into
+ for recording::bitcast. */
+
+void
+recording::bitcast::replay_into (replayer *r)
+{
+ set_playback_obj (r->new_bitcast (playback_location (r, m_loc),
+ m_rvalue->playback_rvalue (),
+ get_type ()->playback_type ()));
+}
+
+/* Implementation of pure virtual hook recording::rvalue::visit_children
+ for recording::bitcast. */
+void
+recording::bitcast::visit_children (rvalue_visitor *v)
+{
+ v->visit (m_rvalue);
+}
+
+/* Implementation of recording::memento::make_debug_string for
+ casts. */
+
+recording::string *
+recording::bitcast::make_debug_string ()
+{
+ enum precedence prec = get_precedence ();
+ return string::from_printf (m_ctxt,
+ "bitcast(%s, %s)",
+ m_rvalue->get_debug_string_parens (prec),
+ get_type ()->get_debug_string ());
+}
+
+/* Implementation of recording::memento::write_reproducer for casts. */
+
+void
+recording::bitcast::write_reproducer (reproducer &r)
+{
+ const char *id = r.make_identifier (this, "rvalue");
+ r.write (" gcc_jit_rvalue *%s =\n"
+ " gcc_jit_context_new_bitcast (%s,\n"
+ " %s, /* gcc_jit_location *loc */\n"
+ " %s, /* gcc_jit_rvalue *rvalue */\n"
+ " %s); /* gcc_jit_type *type */\n",
+ id,
+ r.get_identifier (get_context ()),
+ r.get_identifier (m_loc),
+ r.get_identifier_as_rvalue (m_rvalue),
+ r.get_identifier_as_type (get_type ()));
+}
+
/* The implementation of class gcc::jit::recording::base_call. */
/* The constructor for gcc::jit::recording::base_call. */
diff --git a/gcc/jit/jit-recording.h b/gcc/jit/jit-recording.h
index b663d0f21f5..713aac36ebe 100644
--- a/gcc/jit/jit-recording.h
+++ b/gcc/jit/jit-recording.h
@@ -205,6 +205,11 @@ public:
rvalue *expr,
type *type_);
+ rvalue *
+ new_bitcast (location *loc,
+ rvalue *expr,
+ type *type_);
+
lvalue *
new_array_access (location *loc,
rvalue *ptr,
@@ -1691,6 +1696,33 @@ private:
rvalue *m_rvalue;
};
+class bitcast : public rvalue
+{
+public:
+ bitcast (context *ctxt,
+ location *loc,
+ rvalue *a,
+ type *type_)
+ : rvalue (ctxt, loc, type_),
+ m_rvalue (a)
+ {}
+
+ void replay_into (replayer *r) FINAL OVERRIDE;
+
+ void visit_children (rvalue_visitor *v) FINAL OVERRIDE;
+
+private:
+ string * make_debug_string () FINAL OVERRIDE;
+ void write_reproducer (reproducer &r) FINAL OVERRIDE;
+ enum precedence get_precedence () const FINAL OVERRIDE
+ {
+ return PRECEDENCE_CAST;
+ }
+
+private:
+ rvalue *m_rvalue;
+};
+
class base_call : public rvalue
{
public:
diff --git a/gcc/jit/libgccjit.c b/gcc/jit/libgccjit.c
index 03704ef10b8..cd8516d1c4d 100644
--- a/gcc/jit/libgccjit.c
+++ b/gcc/jit/libgccjit.c
@@ -2405,6 +2405,34 @@ gcc_jit_context_new_cast (gcc_jit_context *ctxt,
return static_cast <gcc_jit_rvalue *> (ctxt->new_cast (loc, rvalue, type));
}
+/* Public entrypoint. See description in libgccjit.h.
+
+ After error-checking, the real work is done by the
+ gcc::jit::recording::context::new_bitcast method in jit-recording.c. */
+
+gcc_jit_rvalue *
+gcc_jit_context_new_bitcast (gcc_jit_context *ctxt,
+ gcc_jit_location *loc,
+ gcc_jit_rvalue *rvalue,
+ gcc_jit_type *type)
+{
+ RETURN_NULL_IF_FAIL (ctxt, NULL, loc, "NULL context");
+ JIT_LOG_FUNC (ctxt->get_logger ());
+ /* LOC can be NULL. */
+ RETURN_NULL_IF_FAIL (rvalue, ctxt, loc, "NULL rvalue");
+ RETURN_NULL_IF_FAIL (type, ctxt, loc, "NULL type");
+ // TODO: check the sizes.
+ /*RETURN_NULL_IF_FAIL_PRINTF3 (
+ is_valid_cast (rvalue->get_type (), type),
+ ctxt, loc,
+ "cannot cast %s from type: %s to type: %s",
+ rvalue->get_debug_string (),
+ rvalue->get_type ()->get_debug_string (),
+ type->get_debug_string ());*/
+
+ return static_cast <gcc_jit_rvalue *> (ctxt->new_bitcast (loc, rvalue, type));
+}
+
/* Public entrypoint. See description in libgccjit.h.
After error-checking, the real work is done by the
diff --git a/gcc/jit/libgccjit.h b/gcc/jit/libgccjit.h
index 2a5ffacb1fe..04d625fb8f3 100644
--- a/gcc/jit/libgccjit.h
+++ b/gcc/jit/libgccjit.h
@@ -1206,6 +1206,21 @@ gcc_jit_context_new_cast (gcc_jit_context *ctxt,
gcc_jit_rvalue *rvalue,
gcc_jit_type *type);
+/* Reinterpret a value as another type.
+
+#define LIBGCCJIT_HAVE_gcc_jit_context_new_bitcast
+
+ The types must be of the same size.
+
+ This API entrypoint was added in LIBGCCJIT_ABI_20; you can test for its
+ presence using
+ #ifdef LIBGCCJIT_HAVE_gcc_jit_context_new_bitcast */
+extern gcc_jit_rvalue *
+gcc_jit_context_new_bitcast (gcc_jit_context *ctxt,
+ gcc_jit_location *loc,
+ gcc_jit_rvalue *rvalue,
+ gcc_jit_type *type);
+
extern gcc_jit_lvalue *
gcc_jit_context_new_array_access (gcc_jit_context *ctxt,
gcc_jit_location *loc,
diff --git a/gcc/jit/libgccjit.map b/gcc/jit/libgccjit.map
index f373fd39ac7..7b6f415ac82 100644
--- a/gcc/jit/libgccjit.map
+++ b/gcc/jit/libgccjit.map
@@ -238,8 +238,14 @@ LIBGCCJIT_ABI_18 {
} LIBGCCJIT_ABI_17;
LIBGCCJIT_ABI_19 {
+ global:
gcc_jit_context_new_array_constructor;
gcc_jit_context_new_struct_constructor;
gcc_jit_context_new_union_constructor;
gcc_jit_global_set_initializer_rvalue;
} LIBGCCJIT_ABI_18;
+
+LIBGCCJIT_ABI_20 {
+ global:
+ gcc_jit_context_new_bitcast;
+} LIBGCCJIT_ABI_19;
diff --git a/gcc/testsuite/jit.dg/all-non-failing-tests.h b/gcc/testsuite/jit.dg/all-non-failing-tests.h
index 29afe064db6..656351edce1 100644
--- a/gcc/testsuite/jit.dg/all-non-failing-tests.h
+++ b/gcc/testsuite/jit.dg/all-non-failing-tests.h
@@ -77,6 +77,13 @@
/* test-builtin-unreachable.c: We don't add this one, since it touches
the optimization level of the context as a whole. */
+/* test-bitcast.c */
+#define create_code create_code_bitcast
+#define verify_code verify_code_bitcast
+#include "test-bitcast.c"
+#undef create_code
+#undef verify_code
+
/* test-calling-external-function.c */
#define create_code create_code_calling_external_function
#define verify_code verify_code_calling_external_function
@@ -400,6 +407,9 @@ const struct testcase testcases[] = {
{"builtin-memcpy",
create_code_builtin_memcpy,
verify_code_builtin_memcpy},
+ {"bitcast",
+ create_code_bitcast,
+ verify_code_bitcast},
{"calling_external_function",
create_code_calling_external_function,
verify_code_calling_external_function},
diff --git a/gcc/testsuite/jit.dg/test-bitcast.c b/gcc/testsuite/jit.dg/test-bitcast.c
new file mode 100644
index 00000000000..2d70622051a
--- /dev/null
+++ b/gcc/testsuite/jit.dg/test-bitcast.c
@@ -0,0 +1,60 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.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:
+int
+my_bitcast (double x)
+{
+ return bitcast(x, int);
+}
+ */
+ gcc_jit_type *int_type =
+ gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_INT);
+ gcc_jit_type *double_type =
+ gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_FLOAT);
+
+ gcc_jit_param *x =
+ gcc_jit_context_new_param (
+ ctxt,
+ NULL,
+ double_type, "x");
+ gcc_jit_param *params[1] = {x};
+ gcc_jit_function *func =
+ gcc_jit_context_new_function (ctxt,
+ NULL,
+ GCC_JIT_FUNCTION_EXPORTED,
+ int_type,
+ "my_bitcast",
+ 1, params, 0);
+
+ gcc_jit_block *initial =
+ gcc_jit_function_new_block (func, "initial");
+
+ gcc_jit_block_end_with_return(initial, NULL,
+ gcc_jit_context_new_bitcast(ctxt,
+ NULL,
+ gcc_jit_param_as_rvalue(x),
+ int_type
+ ));
+}
+
+void
+verify_code (gcc_jit_context *ctxt, gcc_jit_result *result)
+{
+ typedef int (*my_bitcast_fn_type) (double);
+ CHECK_NON_NULL (result);
+ my_bitcast_fn_type my_bitcast =
+ (my_bitcast_fn_type)gcc_jit_result_get_code (result, "my_bitcast");
+ CHECK_NON_NULL (my_bitcast);
+ int val = my_bitcast (-5.1298714);
+ note ("my_bitcast returned: %d", val);
+ CHECK_VALUE (val, 35569201);
+}
diff --git a/gcc/tree.c b/gcc/tree.c
index d98b77db50b..e4bf4e84675 100644
--- a/gcc/tree.c
+++ b/gcc/tree.c
@@ -6963,6 +6963,14 @@ build_reference_type (tree to_type)
(HOST_BITS_PER_WIDE_INT > 64 ? HOST_BITS_PER_WIDE_INT : 64)
static GTY(()) tree nonstandard_integer_type_cache[2 * MAX_INT_CACHED_PREC + 2];
+void clear_nonstandard_integer_type_cache (void)
+{
+ for (size_t i = 0 ; i < 2 * MAX_INT_CACHED_PREC + 2 ; i++)
+ {
+ nonstandard_integer_type_cache[i] = NULL;
+ }
+}
+
/* Builds a signed or unsigned integer type of precision PRECISION.
Used for C bitfields whose precision does not match that of
built-in target types. */
diff --git a/gcc/tree.h b/gcc/tree.h
index 318019c4dc5..640b492802c 100644
--- a/gcc/tree.h
+++ b/gcc/tree.h
@@ -5385,6 +5385,7 @@ extern bool real_minus_onep (const_tree);
extern void init_ttree (void);
extern void build_common_tree_nodes (bool);
extern void build_common_builtin_nodes (void);
+extern void clear_nonstandard_integer_type_cache (void);
extern tree build_nonstandard_integer_type (unsigned HOST_WIDE_INT, int);
extern tree build_nonstandard_boolean_type (unsigned HOST_WIDE_INT);
extern tree build_range_type (tree, tree, tree);
--
2.26.2.7.g19db9cfb68.dirty
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH] libgccjit: Add support for bitcasts [PR104071]
2022-01-18 0:30 ` Antoni Boucher
@ 2022-01-18 23:06 ` David Malcolm
2022-01-21 23:41 ` Antoni Boucher
0 siblings, 1 reply; 7+ messages in thread
From: David Malcolm @ 2022-01-18 23:06 UTC (permalink / raw)
To: Antoni Boucher, gcc-patches, jit
On Mon, 2022-01-17 at 19:30 -0500, Antoni Boucher via Gcc-patches
wrote:
> I was missing the define, so I added it.
> Here's the new patch with it.
Thanks for the patch.
> Le lundi 17 janvier 2022 à 17:18 -0500, Antoni Boucher via Jit a
> écrit :
> > Hi.
> > This patch add support for bitcasts in libgccjit.
> >
> > It passes the JIT tests, but since I added a function in tree.c, I
> > wonder if I should run the whole testsuite.
We're in stage 4 for GCC 12 now, so we need to be especially careful
and conservative about every change. A strict reading on the rules is
that we shouldn't be adding new features - but if they're confined to
libgccjit we may be able to get release manager approval.
> >
> > David, you can now disregard my question in my email about 128-bit
> > integers regarding my issue with initialize_sizetypes being called
> > multiple times because this patch fix this issue.
> > I turns out there was a cache of types that needed to be cleared
> > when
> > you initialize the JIT.
> >
> > The check for sizes is pending, because it requires the updates to
> > get_size I made in my patch for 128-bit integers.
Sorry, I seem to have mislaid that patch; do you have the "Subject"
line handy?
Do you have a list of the patches I need to review?
As for this patch, overall I like it, but there are various nits...
> >
> > Thanks for the review!
> 2022-01-17 Antoni Boucher <bouanto@zoho.com>
>
> gcc/jit/
> PR target/104071
Should be "jit" rather than "target".
Various source files are now .cc rather than .c after yesterday's big
renaming.
> * docs/topics/compatibility.rst (LIBGCCJIT_ABI_20): New ABI tag.
> * docs/topics/expressions.rst: Add documentation for the
> function gcc_jit_context_new_bitcast.
> * dummy-frontend.c: clear the cache of non-standard integer
> types to avoid having issues with some optimizations of
> bitcast where the SSA_NAME will have a size of a cached
> integer type that should have been invalidated, causing a
> comparison of integer constant to fail.
> * jit-playback.c: New function (new_bitcast).
> * jit-playback.h: New function (new_bitcast).
> * jit-recording.c: New functions (new_bitcast,
> bitcast::replay_into, bitcast::visit_children,
> bitcast::make_debug_string, bitcast::write_reproducer).
> * jit-recording.h: New calss (bitcast) and new function
> (new_bitcast, bitcast::replay_into, bitcast::visit_children,
> bitcast::make_debug_string, bitcast::write_reproducer,
> bitcast::get_precedence).
> * libgccjit.c: New function (gcc_jit_context_new_bitcast)
> * libgccjit.h: New function (gcc_jit_context_new_bitcast)
> * libgccjit.map (LIBGCCJIT_ABI_20): New ABI tag.
>
> gcc/testsuite/
> PR target/104071
> * jit.dg/all-non-failing-tests.h: Add new test-bitcast.
> * jit.dg/test-bitcast.c: New test.
>
> gcc/
> PR target/104071
> * tree.c: New function (clear_nonstandard_integer_type_cache).
> * tree.h: New function (clear_nonstandard_integer_type_cache).
> ---
> gcc/jit/docs/topics/compatibility.rst | 9 +++
> gcc/jit/docs/topics/expressions.rst | 17 +++++
> gcc/jit/dummy-frontend.c | 2 +
> gcc/jit/jit-playback.c | 13 ++++
> gcc/jit/jit-playback.h | 5 ++
> gcc/jit/jit-recording.c | 66 ++++++++++++++++++++
> gcc/jit/jit-recording.h | 32 ++++++++++
> gcc/jit/libgccjit.c | 28 +++++++++
> gcc/jit/libgccjit.h | 15 +++++
> gcc/jit/libgccjit.map | 6 ++
> gcc/testsuite/jit.dg/all-non-failing-tests.h | 10 +++
> gcc/testsuite/jit.dg/test-bitcast.c | 60 ++++++++++++++++++
> gcc/tree.c | 8 +++
> gcc/tree.h | 1 +
> 14 files changed, 272 insertions(+)
> create mode 100644 gcc/testsuite/jit.dg/test-bitcast.c
>
> diff --git a/gcc/jit/docs/topics/compatibility.rst b/gcc/jit/docs/topics/compatibility.rst
> index 16cebe31a10..b5a6b704dda 100644
> --- a/gcc/jit/docs/topics/compatibility.rst
> +++ b/gcc/jit/docs/topics/compatibility.rst
> @@ -302,3 +302,12 @@ thread-local storage model of a variable:
> section of a variable:
>
> * :func:`gcc_jit_lvalue_set_link_section`
> +
> +.. _LIBGCCJIT_ABI_20:
> +
> +``LIBGCCJIT_ABI_20``
> +-----------------------
> +``LIBGCCJIT_ABI_20`` covers the addition of an API entrypoint to bitcast a
> +value from one type to another:
> +
> + * :func:`gcc_jit_context_new_bitcast`
> diff --git a/gcc/jit/docs/topics/expressions.rst b/gcc/jit/docs/topics/expressions.rst
> index 791a20398ca..1328a53f70f 100644
> --- a/gcc/jit/docs/topics/expressions.rst
> +++ b/gcc/jit/docs/topics/expressions.rst
> @@ -649,6 +649,23 @@ Type-coercion
> * int <-> bool
> * P* <-> Q*, for pointer types P and Q
>
> +.. function:: gcc_jit_rvalue *\
> + gcc_jit_context_new_bitcast (gcc_jit_context *ctxt,\
> + gcc_jit_location *loc,\
> + gcc_jit_rvalue *rvalue,\
> + gcc_jit_type *type)
> +
> + Given an rvalue of T, bitcast it to another type.
I think it's worth defining what "bitcast" means in the docs here;
presumably you mean something like "generating a new rvalue by
interpreting the bits of the input rvalue according to the layout of
type" or somesuch.
> +
> + The type of rvalue must be the same size as the size of ``type``.
> +
> + This entrypoint was added in :ref:`LIBGCCJIT_ABI_20`; you can test for
> + its presence using
> +
> + .. code-block:: c
> +
> + #ifdef LIBGCCJIT_HAVE_gcc_jit_context_new_bitcast
> +
> Lvalues
> -------
>
> diff --git a/gcc/jit/dummy-frontend.c b/gcc/jit/dummy-frontend.c
> index 84ff359bfe3..c3da97642e3 100644
> --- a/gcc/jit/dummy-frontend.c
> +++ b/gcc/jit/dummy-frontend.c
> @@ -592,6 +592,8 @@ jit_langhook_init (void)
> global_dc->begin_diagnostic = jit_begin_diagnostic;
> global_dc->end_diagnostic = jit_end_diagnostic;
>
> + clear_nonstandard_integer_type_cache ();
> +
I've been putting code to cleanup global state in foo.c into
foo_c_finalize functions; I'm testing a patch right now to rename these
to foo_cc_finalize functions to reflect the renaming of .c to .cc
These cleanup functions are called from toplev::finalize.
I think it would be better to invoke this cleanup from a new
tree_cc_finalize that follows that pattern.
> build_common_tree_nodes (false);
>
> /* I don't know why this has to be done explicitly. */
[...snip...]
> diff --git a/gcc/jit/libgccjit.c b/gcc/jit/libgccjit.c
> index 03704ef10b8..cd8516d1c4d 100644
> --- a/gcc/jit/libgccjit.c
> +++ b/gcc/jit/libgccjit.c
> @@ -2405,6 +2405,34 @@ gcc_jit_context_new_cast (gcc_jit_context *ctxt,
> return static_cast <gcc_jit_rvalue *> (ctxt->new_cast (loc, rvalue, type));
> }
>
> +/* Public entrypoint. See description in libgccjit.h.
> +
> + After error-checking, the real work is done by the
> + gcc::jit::recording::context::new_bitcast method in jit-recording.c. */
> +
> +gcc_jit_rvalue *
> +gcc_jit_context_new_bitcast (gcc_jit_context *ctxt,
> + gcc_jit_location *loc,
> + gcc_jit_rvalue *rvalue,
> + gcc_jit_type *type)
> +{
> + RETURN_NULL_IF_FAIL (ctxt, NULL, loc, "NULL context");
> + JIT_LOG_FUNC (ctxt->get_logger ());
> + /* LOC can be NULL. */
> + RETURN_NULL_IF_FAIL (rvalue, ctxt, loc, "NULL rvalue");
> + RETURN_NULL_IF_FAIL (type, ctxt, loc, "NULL type");
> + // TODO: check the sizes.
> + /*RETURN_NULL_IF_FAIL_PRINTF3 (
> + is_valid_cast (rvalue->get_type (), type),
> + ctxt, loc,
> + "cannot cast %s from type: %s to type: %s",
> + rvalue->get_debug_string (),
> + rvalue->get_type ()->get_debug_string (),
> + type->get_debug_string ());*/
I belive that in general we can't do the checking for equal size until
we have trees i.e. at playback time. I suspect that if the user gets
this wrong, it will lead to an internal compiler error at playback
time.
Please can you add a testcase that tests mismatching sizes e.g. trying
to interpret an int as a array of 4096 bytes, or something similar
that's wildly wrong (ideally coverage for casting in both directions).
Ideally we can generate a useful error message, or, at least, not
crash.
> +
> + return static_cast <gcc_jit_rvalue *> (ctxt->new_bitcast (loc, rvalue, type));
> +}
> +
> /* Public entrypoint. See description in libgccjit.h.
>
> After error-checking, the real work is done by the
[...snip...]
> diff --git a/gcc/testsuite/jit.dg/all-non-failing-tests.h b/gcc/testsuite/jit.dg/all-non-failing-tests.h
> index 29afe064db6..656351edce1 100644
> --- a/gcc/testsuite/jit.dg/all-non-failing-tests.h
> +++ b/gcc/testsuite/jit.dg/all-non-failing-tests.h
> @@ -77,6 +77,13 @@
> /* test-builtin-unreachable.c: We don't add this one, since it touches
> the optimization level of the context as a whole. */
>
> +/* test-bitcast.c */
> +#define create_code create_code_bitcast
> +#define verify_code verify_code_bitcast
> +#include "test-bitcast.c"
> +#undef create_code
> +#undef verify_code
> +
> /* test-calling-external-function.c */
> #define create_code create_code_calling_external_function
> #define verify_code verify_code_calling_external_function
> @@ -400,6 +407,9 @@ const struct testcase testcases[] = {
> {"builtin-memcpy",
> create_code_builtin_memcpy,
> verify_code_builtin_memcpy},
> + {"bitcast",
> + create_code_bitcast,
> + verify_code_bitcast},
> {"calling_external_function",
> create_code_calling_external_function,
> verify_code_calling_external_function},
> diff --git a/gcc/testsuite/jit.dg/test-bitcast.c b/gcc/testsuite/jit.dg/test-bitcast.c
> new file mode 100644
> index 00000000000..2d70622051a
> --- /dev/null
> +++ b/gcc/testsuite/jit.dg/test-bitcast.c
> @@ -0,0 +1,60 @@
> +#include <stdlib.h>
> +#include <stdio.h>
> +#include <string.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:
> +int
> +my_bitcast (double x)
> +{
> + return bitcast(x, int);
> +}
> + */
> + gcc_jit_type *int_type =
> + gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_INT);
> + gcc_jit_type *double_type =
> + gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_FLOAT);
This says "double_type" but is GCC_JIT_TYPE_FLOAT.
I don't think we're guaranteed that sizeof(int) == sizeof(float) on all targets.
> +
> + gcc_jit_param *x =
> + gcc_jit_context_new_param (
> + ctxt,
> + NULL,
> + double_type, "x");
> + gcc_jit_param *params[1] = {x};
> + gcc_jit_function *func =
> + gcc_jit_context_new_function (ctxt,
> + NULL,
> + GCC_JIT_FUNCTION_EXPORTED,
> + int_type,
> + "my_bitcast",
> + 1, params, 0);
> +
> + gcc_jit_block *initial =
> + gcc_jit_function_new_block (func, "initial");
> +
> + gcc_jit_block_end_with_return(initial, NULL,
> + gcc_jit_context_new_bitcast(ctxt,
> + NULL,
> + gcc_jit_param_as_rvalue(x),
> + int_type
> + ));
> +}
> +
> +void
> +verify_code (gcc_jit_context *ctxt, gcc_jit_result *result)
> +{
> + typedef int (*my_bitcast_fn_type) (double);
> + CHECK_NON_NULL (result);
> + my_bitcast_fn_type my_bitcast =
> + (my_bitcast_fn_type)gcc_jit_result_get_code (result,
"my_bitcast");
> + CHECK_NON_NULL (my_bitcast);
> + int val = my_bitcast (-5.1298714);
> + note ("my_bitcast returned: %d", val);
> + CHECK_VALUE (val, 35569201);
> +}
> diff --git a/gcc/tree.c b/gcc/tree.c
> index d98b77db50b..e4bf4e84675 100644
> --- a/gcc/tree.c
> +++ b/gcc/tree.c
> @@ -6963,6 +6963,14 @@ build_reference_type (tree to_type)
> (HOST_BITS_PER_WIDE_INT > 64 ? HOST_BITS_PER_WIDE_INT : 64)
> static GTY(()) tree nonstandard_integer_type_cache[2 *
MAX_INT_CACHED_PREC + 2];
>
> +void clear_nonstandard_integer_type_cache (void)
> +{
> + for (size_t i = 0 ; i < 2 * MAX_INT_CACHED_PREC + 2 ; i++)
> + {
> + nonstandard_integer_type_cache[i] = NULL;
> + }
> +}
> +
As noted above (for gcc/jit/dummy-frontend.c), make this static, and
call it from a new tree_cc_finalize function, and call that from
toplev::finalize.
> /* Builds a signed or unsigned integer type of precision PRECISION.
> Used for C bitfields whose precision does not match that of
> built-in target types. */
> diff --git a/gcc/tree.h b/gcc/tree.h
> index 318019c4dc5..640b492802c 100644
> --- a/gcc/tree.h
> +++ b/gcc/tree.h
> @@ -5385,6 +5385,7 @@ extern bool real_minus_onep (const_tree);
> extern void init_ttree (void);
> extern void build_common_tree_nodes (bool);
> extern void build_common_builtin_nodes (void);
> +extern void clear_nonstandard_integer_type_cache (void);
...and get rid of this in favor of a tree_cc_finalize.
> extern tree build_nonstandard_integer_type (unsigned HOST_WIDE_INT,
int);
> extern tree build_nonstandard_boolean_type (unsigned HOST_WIDE_INT);
> extern tree build_range_type (tree, tree, tree);
> --
> 2.26.2.7.g19db9cfb68.dirty
>
Hope this is constructive; thanks again for the patch
Dave
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH] libgccjit: Add support for bitcasts [PR104071]
2022-01-18 23:06 ` David Malcolm
@ 2022-01-21 23:41 ` Antoni Boucher
2022-04-08 19:22 ` David Malcolm
0 siblings, 1 reply; 7+ messages in thread
From: Antoni Boucher @ 2022-01-21 23:41 UTC (permalink / raw)
To: David Malcolm, gcc-patches, jit
[-- Attachment #1: Type: text/plain, Size: 17161 bytes --]
Hi.
Here's the updated patch.
See comments below.
Le mardi 18 janvier 2022 à 18:06 -0500, David Malcolm a écrit :
> On Mon, 2022-01-17 at 19:30 -0500, Antoni Boucher via Gcc-patches
> wrote:
> > I was missing the define, so I added it.
> > Here's the new patch with it.
>
> Thanks for the patch.
>
> > Le lundi 17 janvier 2022 à 17:18 -0500, Antoni Boucher via Jit a
> > écrit :
> > > Hi.
> > > This patch add support for bitcasts in libgccjit.
> > >
> > > It passes the JIT tests, but since I added a function in tree.c,
> > > I
> > > wonder if I should run the whole testsuite.
>
> We're in stage 4 for GCC 12 now, so we need to be especially careful
> and conservative about every change. A strict reading on the rules
> is
> that we shouldn't be adding new features - but if they're confined to
> libgccjit we may be able to get release manager approval.
Ok, if the 4 patches currently being reviewed (and listed here:
https://github.com/antoyo/libgccjit-patches) were included in gcc 12,
I'd be able to build rustc_codegen_gcc with an unpatched gcc.
It is to be noted however, that I'll need more patches for future work.
Off the top of my head, I'll at least need a patch for the inline
attribute, try/catch and target-specific builtins.
The last 2 features will probably take some time to implement, so I'll
let you judge if you think it's worth merging the 4 patches currently
being reviewed for gcc 12.
>
> > >
> > > David, you can now disregard my question in my email about 128-
> > > bit
> > > integers regarding my issue with initialize_sizetypes being
> > > called
> > > multiple times because this patch fix this issue.
> > > I turns out there was a cache of types that needed to be cleared
> > > when
> > > you initialize the JIT.
> > >
> > > The check for sizes is pending, because it requires the updates
> > > to
> > > get_size I made in my patch for 128-bit integers.
>
> Sorry, I seem to have mislaid that patch; do you have the "Subject"
> line handy?
I recently sent an email with that patch updated, but here's the
subject line:
[PATCH] libgccjit: Add support for sized integer types, including 128-
bit integers [PR95325]
>
> Do you have a list of the patches I need to review?
Yes, on this repo:
https://github.com/antoyo/libgccjit-patches
They are outdated but I can update them if you want.
>
> As for this patch, overall I like it, but there are various nits...
>
> > >
> > > Thanks for the review!
>
> > 2022-01-17 Antoni Boucher <bouanto@zoho.com>
> >
> > gcc/jit/
> > PR target/104071
>
> Should be "jit" rather than "target".
>
> Various source files are now .cc rather than .c after yesterday's big
> renaming.
>
> > * docs/topics/compatibility.rst (LIBGCCJIT_ABI_20): New ABI
> > tag.
> > * docs/topics/expressions.rst: Add documentation for the
> > function gcc_jit_context_new_bitcast.
> > * dummy-frontend.c: clear the cache of non-standard integer
> > types to avoid having issues with some optimizations of
> > bitcast where the SSA_NAME will have a size of a cached
> > integer type that should have been invalidated, causing a
> > comparison of integer constant to fail.
> > * jit-playback.c: New function (new_bitcast).
> > * jit-playback.h: New function (new_bitcast).
> > * jit-recording.c: New functions (new_bitcast,
> > bitcast::replay_into, bitcast::visit_children,
> > bitcast::make_debug_string, bitcast::write_reproducer).
> > * jit-recording.h: New calss (bitcast) and new function
> > (new_bitcast, bitcast::replay_into,
> > bitcast::visit_children,
> > bitcast::make_debug_string, bitcast::write_reproducer,
> > bitcast::get_precedence).
> > * libgccjit.c: New function (gcc_jit_context_new_bitcast)
> > * libgccjit.h: New function (gcc_jit_context_new_bitcast)
> > * libgccjit.map (LIBGCCJIT_ABI_20): New ABI tag.
> >
> > gcc/testsuite/
> > PR target/104071
> > * jit.dg/all-non-failing-tests.h: Add new test-bitcast.
> > * jit.dg/test-bitcast.c: New test.
> >
> > gcc/
> > PR target/104071
> > * tree.c: New function
> > (clear_nonstandard_integer_type_cache).
> > * tree.h: New function
> > (clear_nonstandard_integer_type_cache).
> > ---
> > gcc/jit/docs/topics/compatibility.rst | 9 +++
> > gcc/jit/docs/topics/expressions.rst | 17 +++++
> > gcc/jit/dummy-frontend.c | 2 +
> > gcc/jit/jit-playback.c | 13 ++++
> > gcc/jit/jit-playback.h | 5 ++
> > gcc/jit/jit-recording.c | 66
> > ++++++++++++++++++++
> > gcc/jit/jit-recording.h | 32 ++++++++++
> > gcc/jit/libgccjit.c | 28 +++++++++
> > gcc/jit/libgccjit.h | 15 +++++
> > gcc/jit/libgccjit.map | 6 ++
> > gcc/testsuite/jit.dg/all-non-failing-tests.h | 10 +++
> > gcc/testsuite/jit.dg/test-bitcast.c | 60
> > ++++++++++++++++++
> > gcc/tree.c | 8 +++
> > gcc/tree.h | 1 +
> > 14 files changed, 272 insertions(+)
> > create mode 100644 gcc/testsuite/jit.dg/test-bitcast.c
> >
> > diff --git a/gcc/jit/docs/topics/compatibility.rst
> > b/gcc/jit/docs/topics/compatibility.rst
> > index 16cebe31a10..b5a6b704dda 100644
> > --- a/gcc/jit/docs/topics/compatibility.rst
> > +++ b/gcc/jit/docs/topics/compatibility.rst
> > @@ -302,3 +302,12 @@ thread-local storage model of a variable:
> > section of a variable:
> >
> > * :func:`gcc_jit_lvalue_set_link_section`
> > +
> > +.. _LIBGCCJIT_ABI_20:
> > +
> > +``LIBGCCJIT_ABI_20``
> > +-----------------------
> > +``LIBGCCJIT_ABI_20`` covers the addition of an API entrypoint to
> > bitcast a
> > +value from one type to another:
> > +
> > + * :func:`gcc_jit_context_new_bitcast`
> > diff --git a/gcc/jit/docs/topics/expressions.rst
> > b/gcc/jit/docs/topics/expressions.rst
> > index 791a20398ca..1328a53f70f 100644
> > --- a/gcc/jit/docs/topics/expressions.rst
> > +++ b/gcc/jit/docs/topics/expressions.rst
> > @@ -649,6 +649,23 @@ Type-coercion
> > * int <-> bool
> > * P* <-> Q*, for pointer types P and Q
> >
> > +.. function:: gcc_jit_rvalue *\
> > + gcc_jit_context_new_bitcast (gcc_jit_context *ctxt,\
> > + gcc_jit_location *loc,\
> > + gcc_jit_rvalue
> > *rvalue,\
> > + gcc_jit_type *type)
> > +
> > + Given an rvalue of T, bitcast it to another type.
>
> I think it's worth defining what "bitcast" means in the docs here;
> presumably you mean something like "generating a new rvalue by
> interpreting the bits of the input rvalue according to the layout of
> type" or somesuch.
Done.
>
>
> > +
> > + The type of rvalue must be the same size as the size of
> > ``type``.
> > +
> > + This entrypoint was added in :ref:`LIBGCCJIT_ABI_20`; you can
> > test for
> > + its presence using
> > +
> > + .. code-block:: c
> > +
> > + #ifdef LIBGCCJIT_HAVE_gcc_jit_context_new_bitcast
> > +
> > Lvalues
> > -------
> >
> > diff --git a/gcc/jit/dummy-frontend.c b/gcc/jit/dummy-frontend.c
> > index 84ff359bfe3..c3da97642e3 100644
> > --- a/gcc/jit/dummy-frontend.c
> > +++ b/gcc/jit/dummy-frontend.c
> > @@ -592,6 +592,8 @@ jit_langhook_init (void)
> > global_dc->begin_diagnostic = jit_begin_diagnostic;
> > global_dc->end_diagnostic = jit_end_diagnostic;
> >
> > + clear_nonstandard_integer_type_cache ();
> > +
>
> I've been putting code to cleanup global state in foo.c into
> foo_c_finalize functions; I'm testing a patch right now to rename
> these
> to foo_cc_finalize functions to reflect the renaming of .c to .cc
> These cleanup functions are called from toplev::finalize.
>
> I think it would be better to invoke this cleanup from a new
> tree_cc_finalize that follows that pattern.
Done.
>
> > build_common_tree_nodes (false);
> >
> > /* I don't know why this has to be done explicitly. */
>
> [...snip...]
>
> > diff --git a/gcc/jit/libgccjit.c b/gcc/jit/libgccjit.c
> > index 03704ef10b8..cd8516d1c4d 100644
> > --- a/gcc/jit/libgccjit.c
> > +++ b/gcc/jit/libgccjit.c
> > @@ -2405,6 +2405,34 @@ gcc_jit_context_new_cast (gcc_jit_context
> > *ctxt,
> > return static_cast <gcc_jit_rvalue *> (ctxt->new_cast (loc,
> > rvalue, type));
> > }
> >
> > +/* Public entrypoint. See description in libgccjit.h.
> > +
> > + After error-checking, the real work is done by the
> > + gcc::jit::recording::context::new_bitcast method in jit-
> > recording.c. */
> > +
> > +gcc_jit_rvalue *
> > +gcc_jit_context_new_bitcast (gcc_jit_context *ctxt,
> > + gcc_jit_location *loc,
> > + gcc_jit_rvalue *rvalue,
> > + gcc_jit_type *type)
> > +{
> > + RETURN_NULL_IF_FAIL (ctxt, NULL, loc, "NULL context");
> > + JIT_LOG_FUNC (ctxt->get_logger ());
> > + /* LOC can be NULL. */
> > + RETURN_NULL_IF_FAIL (rvalue, ctxt, loc, "NULL rvalue");
> > + RETURN_NULL_IF_FAIL (type, ctxt, loc, "NULL type");
> > + // TODO: check the sizes.
> > + /*RETURN_NULL_IF_FAIL_PRINTF3 (
> > + is_valid_cast (rvalue->get_type (), type),
> > + ctxt, loc,
> > + "cannot cast %s from type: %s to type: %s",
> > + rvalue->get_debug_string (),
> > + rvalue->get_type ()->get_debug_string (),
> > + type->get_debug_string ());*/
>
> I belive that in general we can't do the checking for equal size
> until
> we have trees i.e. at playback time. I suspect that if the user gets
> this wrong, it will lead to an internal compiler error at playback
> time.
Done.
>
> Please can you add a testcase that tests mismatching sizes e.g.
> trying
> to interpret an int as a array of 4096 bytes, or something similar
> that's wildly wrong (ideally coverage for casting in both
> directions).
Done.
>
> Ideally we can generate a useful error message, or, at least, not
> crash.
>
> > +
> > + return static_cast <gcc_jit_rvalue *> (ctxt->new_bitcast (loc,
> > rvalue, type));
> > +}
> > +
> > /* Public entrypoint. See description in libgccjit.h.
> >
> > After error-checking, the real work is done by the
>
> [...snip...]
>
> > diff --git a/gcc/testsuite/jit.dg/all-non-failing-tests.h
> > b/gcc/testsuite/jit.dg/all-non-failing-tests.h
> > index 29afe064db6..656351edce1 100644
> > --- a/gcc/testsuite/jit.dg/all-non-failing-tests.h
> > +++ b/gcc/testsuite/jit.dg/all-non-failing-tests.h
> > @@ -77,6 +77,13 @@
> > /* test-builtin-unreachable.c: We don't add this one, since it
> > touches
> > the optimization level of the context as a whole. */
> >
> > +/* test-bitcast.c */
> > +#define create_code create_code_bitcast
> > +#define verify_code verify_code_bitcast
> > +#include "test-bitcast.c"
> > +#undef create_code
> > +#undef verify_code
> > +
> > /* test-calling-external-function.c */
> > #define create_code create_code_calling_external_function
> > #define verify_code verify_code_calling_external_function
> > @@ -400,6 +407,9 @@ const struct testcase testcases[] = {
> > {"builtin-memcpy",
> > create_code_builtin_memcpy,
> > verify_code_builtin_memcpy},
> > + {"bitcast",
> > + create_code_bitcast,
> > + verify_code_bitcast},
> > {"calling_external_function",
> > create_code_calling_external_function,
> > verify_code_calling_external_function},
> > diff --git a/gcc/testsuite/jit.dg/test-bitcast.c
> > b/gcc/testsuite/jit.dg/test-bitcast.c
> > new file mode 100644
> > index 00000000000..2d70622051a
> > --- /dev/null
> > +++ b/gcc/testsuite/jit.dg/test-bitcast.c
> > @@ -0,0 +1,60 @@
> > +#include <stdlib.h>
> > +#include <stdio.h>
> > +#include <string.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:
> > +int
> > +my_bitcast (double x)
> > +{
> > + return bitcast(x, int);
> > +}
> > + */
> > + gcc_jit_type *int_type =
> > + gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_INT);
> > + gcc_jit_type *double_type =
> > + gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_FLOAT);
>
> This says "double_type" but is GCC_JIT_TYPE_FLOAT.
>
> I don't think we're guaranteed that sizeof(int) == sizeof(float) on
> all targets.
I switched to using `gcc_jit_context_get_int_type (ctxt, 4, 1)` for the
integer type.
>
> > +
> > + gcc_jit_param *x =
> > + gcc_jit_context_new_param (
> > + ctxt,
> > + NULL,
> > + double_type, "x");
> > + gcc_jit_param *params[1] = {x};
> > + gcc_jit_function *func =
> > + gcc_jit_context_new_function (ctxt,
> > + NULL,
> > + GCC_JIT_FUNCTION_EXPORTED,
> > + int_type,
> > + "my_bitcast",
> > + 1, params, 0);
> > +
> > + gcc_jit_block *initial =
> > + gcc_jit_function_new_block (func, "initial");
> > +
> > + gcc_jit_block_end_with_return(initial, NULL,
> > + gcc_jit_context_new_bitcast(ctxt,
> > + NULL,
> > + gcc_jit_param_as_rvalue(x),
> > + int_type
> > + ));
> > +}
> > +
> > +void
> > +verify_code (gcc_jit_context *ctxt, gcc_jit_result *result)
> > +{
> > + typedef int (*my_bitcast_fn_type) (double);
> > + CHECK_NON_NULL (result);
> > + my_bitcast_fn_type my_bitcast =
> > + (my_bitcast_fn_type)gcc_jit_result_get_code (result,
> "my_bitcast");
> > + CHECK_NON_NULL (my_bitcast);
> > + int val = my_bitcast (-5.1298714);
> > + note ("my_bitcast returned: %d", val);
> > + CHECK_VALUE (val, 35569201);
> > +}
> > diff --git a/gcc/tree.c b/gcc/tree.c
> > index d98b77db50b..e4bf4e84675 100644
> > --- a/gcc/tree.c
> > +++ b/gcc/tree.c
> > @@ -6963,6 +6963,14 @@ build_reference_type (tree to_type)
> > (HOST_BITS_PER_WIDE_INT > 64 ? HOST_BITS_PER_WIDE_INT : 64)
> > static GTY(()) tree nonstandard_integer_type_cache[2 *
> MAX_INT_CACHED_PREC + 2];
> >
> > +void clear_nonstandard_integer_type_cache (void)
> > +{
> > + for (size_t i = 0 ; i < 2 * MAX_INT_CACHED_PREC + 2 ; i++)
> > + {
> > + nonstandard_integer_type_cache[i] = NULL;
> > + }
> > +}
> > +
>
> As noted above (for gcc/jit/dummy-frontend.c), make this static, and
> call it from a new tree_cc_finalize function, and call that from
> toplev::finalize.
>
> > /* Builds a signed or unsigned integer type of precision
> > PRECISION.
> > Used for C bitfields whose precision does not match that of
> > built-in target types. */
> > diff --git a/gcc/tree.h b/gcc/tree.h
> > index 318019c4dc5..640b492802c 100644
> > --- a/gcc/tree.h
> > +++ b/gcc/tree.h
> > @@ -5385,6 +5385,7 @@ extern bool real_minus_onep (const_tree);
> > extern void init_ttree (void);
> > extern void build_common_tree_nodes (bool);
> > extern void build_common_builtin_nodes (void);
> > +extern void clear_nonstandard_integer_type_cache (void);
>
> ...and get rid of this in favor of a tree_cc_finalize.
>
> > extern tree build_nonstandard_integer_type (unsigned
> > HOST_WIDE_INT,
> int);
> > extern tree build_nonstandard_boolean_type (unsigned
> > HOST_WIDE_INT);
> > extern tree build_range_type (tree, tree, tree);
> > --
> > 2.26.2.7.g19db9cfb68.dirty
> >
>
> Hope this is constructive; thanks again for the patch
> Dave
>
[-- Attachment #2: 0001-libgccjit-Add-support-for-bitcasts-PR104071.patch --]
[-- Type: text/x-patch, Size: 20830 bytes --]
From d7f49170394de78471164a9fb8d08ad92508b42a Mon Sep 17 00:00:00 2001
From: Antoni Boucher <bouanto@zoho.com>
Date: Wed, 9 Jun 2021 18:29:14 -0400
Subject: [PATCH] libgccjit: Add support for bitcasts [PR104071]
2022-01-21 Antoni Boucher <bouanto@zoho.com>
gcc/jit/
PR jit/104071
* docs/topics/compatibility.rst (LIBGCCJIT_ABI_21): New ABI tag.
* docs/topics/expressions.rst: Add documentation for the
function gcc_jit_context_new_bitcast.
* jit-playback.cc: New function (new_bitcast).
* jit-playback.h: New function (new_bitcast).
* jit-recording.cc: New functions (new_bitcast,
bitcast::replay_into, bitcast::visit_children,
bitcast::make_debug_string, bitcast::write_reproducer).
* jit-recording.h: New calss (bitcast) and new function
(new_bitcast, bitcast::replay_into, bitcast::visit_children,
bitcast::make_debug_string, bitcast::write_reproducer,
bitcast::get_precedence).
* libgccjit.cc: New function (gcc_jit_context_new_bitcast)
* libgccjit.h: New function (gcc_jit_context_new_bitcast)
* libgccjit.map (LIBGCCJIT_ABI_21): New ABI tag.
gcc/testsuite/
PR jit/104071
* jit.dg/all-non-failing-tests.h: Add new test-bitcast.
* jit.dg/test-bitcast.c: New test.
* jit.dg/test-error-bad-bitcast.c: New test.
* jit.dg/test-error-bad-bitcast2.c: New test.
gcc/
PR jit/104071
* toplev.cc: Call the new function tree_cc_finalize in
toplev::finalize.
* tree.cc: New functions (clear_nonstandard_integer_type_cache
and tree_cc_finalize) to clear the cache of non-standard integer
types to avoid having issues with some optimizations of
bitcast where the SSA_NAME will have a size of a cached
integer type that should have been invalidated, causing a
comparison of integer constant to fail.
* tree.h: New function (tree_cc_finalize).
---
gcc/jit/docs/topics/compatibility.rst | 9 +++
gcc/jit/docs/topics/expressions.rst | 19 ++++++
gcc/jit/jit-playback.cc | 27 ++++++++
gcc/jit/jit-playback.h | 5 ++
gcc/jit/jit-recording.cc | 66 +++++++++++++++++++
gcc/jit/jit-recording.h | 32 +++++++++
gcc/jit/libgccjit.cc | 28 ++++++++
gcc/jit/libgccjit.h | 15 +++++
gcc/jit/libgccjit.map | 9 +++
gcc/testsuite/jit.dg/all-non-failing-tests.h | 10 +++
gcc/testsuite/jit.dg/test-bitcast.c | 60 +++++++++++++++++
gcc/testsuite/jit.dg/test-error-bad-bitcast.c | 62 +++++++++++++++++
.../jit.dg/test-error-bad-bitcast2.c | 62 +++++++++++++++++
gcc/toplev.cc | 1 +
gcc/tree.cc | 15 +++++
gcc/tree.h | 1 +
16 files changed, 421 insertions(+)
create mode 100644 gcc/testsuite/jit.dg/test-bitcast.c
create mode 100644 gcc/testsuite/jit.dg/test-error-bad-bitcast.c
create mode 100644 gcc/testsuite/jit.dg/test-error-bad-bitcast2.c
diff --git a/gcc/jit/docs/topics/compatibility.rst b/gcc/jit/docs/topics/compatibility.rst
index 16cebe31a10..610d9dc175f 100644
--- a/gcc/jit/docs/topics/compatibility.rst
+++ b/gcc/jit/docs/topics/compatibility.rst
@@ -302,3 +302,12 @@ thread-local storage model of a variable:
section of a variable:
* :func:`gcc_jit_lvalue_set_link_section`
+
+.. _LIBGCCJIT_ABI_21:
+
+``LIBGCCJIT_ABI_21``
+-----------------------
+``LIBGCCJIT_ABI_21`` covers the addition of an API entrypoint to bitcast a
+value from one type to another:
+
+ * :func:`gcc_jit_context_new_bitcast`
diff --git a/gcc/jit/docs/topics/expressions.rst b/gcc/jit/docs/topics/expressions.rst
index 791a20398ca..e0b6f426aee 100644
--- a/gcc/jit/docs/topics/expressions.rst
+++ b/gcc/jit/docs/topics/expressions.rst
@@ -649,6 +649,25 @@ Type-coercion
* int <-> bool
* P* <-> Q*, for pointer types P and Q
+.. function:: gcc_jit_rvalue *\
+ gcc_jit_context_new_bitcast (gcc_jit_context *ctxt,\
+ gcc_jit_location *loc,\
+ gcc_jit_rvalue *rvalue,\
+ gcc_jit_type *type)
+
+ Given an rvalue of T, bitcast it to another type, meaning that this will
+ generate a new rvalue by interpreting the bits of ``rvalue`` to the layout
+ of ``type``.
+
+ The type of rvalue must be the same size as the size of ``type``.
+
+ This entrypoint was added in :ref:`LIBGCCJIT_ABI_21`; you can test for
+ its presence using
+
+ .. code-block:: c
+
+ #ifdef LIBGCCJIT_HAVE_gcc_jit_context_new_bitcast
+
Lvalues
-------
diff --git a/gcc/jit/jit-playback.cc b/gcc/jit/jit-playback.cc
index d1835c79863..d2efae1c163 100644
--- a/gcc/jit/jit-playback.cc
+++ b/gcc/jit/jit-playback.cc
@@ -1390,6 +1390,33 @@ new_cast (playback::location *loc,
return new rvalue (this, t_cast);
}
+playback::rvalue *
+playback::context::
+new_bitcast (location *loc,
+ rvalue *expr,
+ type *type_)
+{
+ tree expr_size = TYPE_SIZE (expr->get_type ()->as_tree ());
+ tree type_size = TYPE_SIZE (type_->as_tree ());
+ tree t_expr = expr->as_tree ();
+ tree t_dst_type = type_->as_tree ();
+ if (expr_size != type_size)
+ {
+ active_playback_ctxt->add_error (loc,
+ "bitcast with types of different sizes");
+ fprintf (stderr, "input expression (size: %ld):\n",
+ tree_to_uhwi (expr_size));
+ debug_tree (t_expr);
+ fprintf (stderr, "requested type (size: %ld):\n",
+ tree_to_uhwi (type_size));
+ debug_tree (t_dst_type);
+ }
+ tree t_bitcast = build1 (VIEW_CONVERT_EXPR, t_dst_type, t_expr);
+ if (loc)
+ set_tree_location (t_bitcast, loc);
+ return new rvalue (this, t_bitcast);
+}
+
/* Construct a playback::lvalue instance (wrapping a tree) for an
array access. */
diff --git a/gcc/jit/jit-playback.h b/gcc/jit/jit-playback.h
index c93d7055d43..5b107be9d69 100644
--- a/gcc/jit/jit-playback.h
+++ b/gcc/jit/jit-playback.h
@@ -180,6 +180,11 @@ public:
rvalue *expr,
type *type_);
+ rvalue *
+ new_bitcast (location *loc,
+ rvalue *expr,
+ type *type_);
+
lvalue *
new_array_access (location *loc,
rvalue *ptr,
diff --git a/gcc/jit/jit-recording.cc b/gcc/jit/jit-recording.cc
index 1e3fadfacd7..e1029086da8 100644
--- a/gcc/jit/jit-recording.cc
+++ b/gcc/jit/jit-recording.cc
@@ -1242,6 +1242,22 @@ recording::context::new_cast (recording::location *loc,
return result;
}
+/* Create a recording::bitcast instance and add it to this context's list
+ of mementos.
+
+ Implements the post-error-checking part of
+ gcc_jit_context_new_bitcast. */
+
+recording::rvalue *
+recording::context::new_bitcast (location *loc,
+ rvalue *expr,
+ type *type_)
+{
+ recording::rvalue *result = new bitcast (this, loc, expr, type_);
+ record (result);
+ return result;
+}
+
/* Create a recording::call instance and add it to this context's list
of mementos.
@@ -5740,6 +5756,56 @@ recording::cast::write_reproducer (reproducer &r)
r.get_identifier_as_type (get_type ()));
}
+/* Implementation of pure virtual hook recording::memento::replay_into
+ for recording::bitcast. */
+
+void
+recording::bitcast::replay_into (replayer *r)
+{
+ set_playback_obj (r->new_bitcast (playback_location (r, m_loc),
+ m_rvalue->playback_rvalue (),
+ get_type ()->playback_type ()));
+}
+
+/* Implementation of pure virtual hook recording::rvalue::visit_children
+ for recording::bitcast. */
+void
+recording::bitcast::visit_children (rvalue_visitor *v)
+{
+ v->visit (m_rvalue);
+}
+
+/* Implementation of recording::memento::make_debug_string for
+ casts. */
+
+recording::string *
+recording::bitcast::make_debug_string ()
+{
+ enum precedence prec = get_precedence ();
+ return string::from_printf (m_ctxt,
+ "bitcast(%s, %s)",
+ m_rvalue->get_debug_string_parens (prec),
+ get_type ()->get_debug_string ());
+}
+
+/* Implementation of recording::memento::write_reproducer for casts. */
+
+void
+recording::bitcast::write_reproducer (reproducer &r)
+{
+ const char *id = r.make_identifier (this, "rvalue");
+ r.write (" gcc_jit_rvalue *%s =\n"
+ " gcc_jit_context_new_bitcast (%s,\n"
+ " %s, /* gcc_jit_location *loc */\n"
+ " %s, /* gcc_jit_rvalue *rvalue */\n"
+ " %s); /* gcc_jit_type *type */\n",
+ id,
+ r.get_identifier (get_context ()),
+ r.get_identifier (m_loc),
+ r.get_identifier_as_rvalue (m_rvalue),
+ r.get_identifier_as_type (get_type ()));
+}
+
/* The implementation of class gcc::jit::recording::base_call. */
/* The constructor for gcc::jit::recording::base_call. */
diff --git a/gcc/jit/jit-recording.h b/gcc/jit/jit-recording.h
index 846d65cb202..ed03b3a24c8 100644
--- a/gcc/jit/jit-recording.h
+++ b/gcc/jit/jit-recording.h
@@ -205,6 +205,11 @@ public:
rvalue *expr,
type *type_);
+ rvalue *
+ new_bitcast (location *loc,
+ rvalue *expr,
+ type *type_);
+
lvalue *
new_array_access (location *loc,
rvalue *ptr,
@@ -1691,6 +1696,33 @@ private:
rvalue *m_rvalue;
};
+class bitcast : public rvalue
+{
+public:
+ bitcast (context *ctxt,
+ location *loc,
+ rvalue *a,
+ type *type_)
+ : rvalue (ctxt, loc, type_),
+ m_rvalue (a)
+ {}
+
+ void replay_into (replayer *r) FINAL OVERRIDE;
+
+ void visit_children (rvalue_visitor *v) FINAL OVERRIDE;
+
+private:
+ string * make_debug_string () FINAL OVERRIDE;
+ void write_reproducer (reproducer &r) FINAL OVERRIDE;
+ enum precedence get_precedence () const FINAL OVERRIDE
+ {
+ return PRECEDENCE_CAST;
+ }
+
+private:
+ rvalue *m_rvalue;
+};
+
class base_call : public rvalue
{
public:
diff --git a/gcc/jit/libgccjit.cc b/gcc/jit/libgccjit.cc
index 4c352e8c93d..6bf1e1ceee0 100644
--- a/gcc/jit/libgccjit.cc
+++ b/gcc/jit/libgccjit.cc
@@ -2405,6 +2405,34 @@ gcc_jit_context_new_cast (gcc_jit_context *ctxt,
return static_cast <gcc_jit_rvalue *> (ctxt->new_cast (loc, rvalue, type));
}
+/* Public entrypoint. See description in libgccjit.h.
+
+ After error-checking, the real work is done by the
+ gcc::jit::recording::context::new_bitcast method in jit-recording.c. */
+
+gcc_jit_rvalue *
+gcc_jit_context_new_bitcast (gcc_jit_context *ctxt,
+ gcc_jit_location *loc,
+ gcc_jit_rvalue *rvalue,
+ gcc_jit_type *type)
+{
+ RETURN_NULL_IF_FAIL (ctxt, NULL, loc, "NULL context");
+ JIT_LOG_FUNC (ctxt->get_logger ());
+ /* LOC can be NULL. */
+ RETURN_NULL_IF_FAIL (rvalue, ctxt, loc, "NULL rvalue");
+ RETURN_NULL_IF_FAIL (type, ctxt, loc, "NULL type");
+ // TODO: check the sizes.
+ /*RETURN_NULL_IF_FAIL_PRINTF3 (
+ is_valid_cast (rvalue->get_type (), type),
+ ctxt, loc,
+ "cannot cast %s from type: %s to type: %s",
+ rvalue->get_debug_string (),
+ rvalue->get_type ()->get_debug_string (),
+ type->get_debug_string ());*/
+
+ return static_cast <gcc_jit_rvalue *> (ctxt->new_bitcast (loc, rvalue, type));
+}
+
/* Public entrypoint. See description in libgccjit.h.
After error-checking, the real work is done by the
diff --git a/gcc/jit/libgccjit.h b/gcc/jit/libgccjit.h
index 2a5ffacb1fe..960e4f4261e 100644
--- a/gcc/jit/libgccjit.h
+++ b/gcc/jit/libgccjit.h
@@ -1206,6 +1206,21 @@ gcc_jit_context_new_cast (gcc_jit_context *ctxt,
gcc_jit_rvalue *rvalue,
gcc_jit_type *type);
+/* Reinterpret a value as another type.
+
+#define LIBGCCJIT_HAVE_gcc_jit_context_new_bitcast
+
+ The types must be of the same size.
+
+ This API entrypoint was added in LIBGCCJIT_ABI_21; you can test for its
+ presence using
+ #ifdef LIBGCCJIT_HAVE_gcc_jit_context_new_bitcast */
+extern gcc_jit_rvalue *
+gcc_jit_context_new_bitcast (gcc_jit_context *ctxt,
+ gcc_jit_location *loc,
+ gcc_jit_rvalue *rvalue,
+ gcc_jit_type *type);
+
extern gcc_jit_lvalue *
gcc_jit_context_new_array_access (gcc_jit_context *ctxt,
gcc_jit_location *loc,
diff --git a/gcc/jit/libgccjit.map b/gcc/jit/libgccjit.map
index f373fd39ac7..38c355437bf 100644
--- a/gcc/jit/libgccjit.map
+++ b/gcc/jit/libgccjit.map
@@ -238,8 +238,17 @@ LIBGCCJIT_ABI_18 {
} LIBGCCJIT_ABI_17;
LIBGCCJIT_ABI_19 {
+ global:
gcc_jit_context_new_array_constructor;
gcc_jit_context_new_struct_constructor;
gcc_jit_context_new_union_constructor;
gcc_jit_global_set_initializer_rvalue;
} LIBGCCJIT_ABI_18;
+
+LIBGCCJIT_ABI_20 {
+} LIBGCCJIT_ABI_19;
+
+LIBGCCJIT_ABI_21 {
+ global:
+ gcc_jit_context_new_bitcast;
+} LIBGCCJIT_ABI_20;
diff --git a/gcc/testsuite/jit.dg/all-non-failing-tests.h b/gcc/testsuite/jit.dg/all-non-failing-tests.h
index 29afe064db6..656351edce1 100644
--- a/gcc/testsuite/jit.dg/all-non-failing-tests.h
+++ b/gcc/testsuite/jit.dg/all-non-failing-tests.h
@@ -77,6 +77,13 @@
/* test-builtin-unreachable.c: We don't add this one, since it touches
the optimization level of the context as a whole. */
+/* test-bitcast.c */
+#define create_code create_code_bitcast
+#define verify_code verify_code_bitcast
+#include "test-bitcast.c"
+#undef create_code
+#undef verify_code
+
/* test-calling-external-function.c */
#define create_code create_code_calling_external_function
#define verify_code verify_code_calling_external_function
@@ -400,6 +407,9 @@ const struct testcase testcases[] = {
{"builtin-memcpy",
create_code_builtin_memcpy,
verify_code_builtin_memcpy},
+ {"bitcast",
+ create_code_bitcast,
+ verify_code_bitcast},
{"calling_external_function",
create_code_calling_external_function,
verify_code_calling_external_function},
diff --git a/gcc/testsuite/jit.dg/test-bitcast.c b/gcc/testsuite/jit.dg/test-bitcast.c
new file mode 100644
index 00000000000..a092fa117e6
--- /dev/null
+++ b/gcc/testsuite/jit.dg/test-bitcast.c
@@ -0,0 +1,60 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.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:
+int
+my_bitcast (double x)
+{
+ return bitcast(x, int);
+}
+ */
+ gcc_jit_type *int_type =
+ gcc_jit_context_get_int_type (ctxt, 4, 1);
+ gcc_jit_type *float_type =
+ gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_FLOAT);
+
+ gcc_jit_param *x =
+ gcc_jit_context_new_param (
+ ctxt,
+ NULL,
+ float_type, "x");
+ gcc_jit_param *params[1] = {x};
+ gcc_jit_function *func =
+ gcc_jit_context_new_function (ctxt,
+ NULL,
+ GCC_JIT_FUNCTION_EXPORTED,
+ int_type,
+ "my_bitcast",
+ 1, params, 0);
+
+ gcc_jit_block *initial =
+ gcc_jit_function_new_block (func, "initial");
+
+ gcc_jit_block_end_with_return(initial, NULL,
+ gcc_jit_context_new_bitcast(ctxt,
+ NULL,
+ gcc_jit_param_as_rvalue(x),
+ int_type
+ ));
+}
+
+void
+verify_code (gcc_jit_context *ctxt, gcc_jit_result *result)
+{
+ typedef int (*my_bitcast_fn_type) (double);
+ CHECK_NON_NULL (result);
+ my_bitcast_fn_type my_bitcast =
+ (my_bitcast_fn_type)gcc_jit_result_get_code (result, "my_bitcast");
+ CHECK_NON_NULL (my_bitcast);
+ int val = my_bitcast (-5.1298714);
+ note ("my_bitcast returned: %d", val);
+ CHECK_VALUE (val, 35569201);
+}
diff --git a/gcc/testsuite/jit.dg/test-error-bad-bitcast.c b/gcc/testsuite/jit.dg/test-error-bad-bitcast.c
new file mode 100644
index 00000000000..642890605ad
--- /dev/null
+++ b/gcc/testsuite/jit.dg/test-error-bad-bitcast.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:
+
+ int
+ test_fn ()
+ {
+ char f[4096];
+ return bitcast(f, int);
+ }
+
+ and verify that the API complains about the bad cast.
+ */
+ gcc_jit_type *int_type =
+ gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_INT);
+ gcc_jit_type *char_type =
+ gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_CHAR);
+
+
+ gcc_jit_type *array_type =
+ gcc_jit_context_new_array_type (ctxt, NULL, char_type, 4096);
+
+ gcc_jit_function *test_fn =
+ gcc_jit_context_new_function (ctxt, NULL,
+ GCC_JIT_FUNCTION_EXPORTED,
+ int_type,
+ "test_fn",
+ 0, NULL,
+ 0);
+ gcc_jit_lvalue *f =
+ gcc_jit_function_new_local (
+ test_fn,
+ NULL,
+ array_type, "f");
+
+ gcc_jit_block *block = gcc_jit_function_new_block (test_fn, NULL);
+
+ gcc_jit_block_end_with_return (
+ block, NULL,
+ gcc_jit_context_new_bitcast (ctxt, NULL,
+ gcc_jit_lvalue_as_rvalue (f),
+ int_type));
+}
+
+void
+verify_code (gcc_jit_context *ctxt, gcc_jit_result *result)
+{
+ CHECK_VALUE (result, NULL);
+
+ /* Verify that the correct error message was emitted. */
+ CHECK_STRING_VALUE (gcc_jit_context_get_first_error (ctxt),
+ "bitcast with types of different sizes");
+}
+
diff --git a/gcc/testsuite/jit.dg/test-error-bad-bitcast2.c b/gcc/testsuite/jit.dg/test-error-bad-bitcast2.c
new file mode 100644
index 00000000000..602ae407076
--- /dev/null
+++ b/gcc/testsuite/jit.dg/test-error-bad-bitcast2.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:
+
+ char[4096]
+ test_fn ()
+ {
+ int f;
+ return bitcast(f, char[4096]);
+ }
+
+ and verify that the API complains about the bad cast.
+ */
+ gcc_jit_type *int_type =
+ gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_INT);
+ gcc_jit_type *char_type =
+ gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_CHAR);
+
+
+ gcc_jit_type *array_type =
+ gcc_jit_context_new_array_type (ctxt, NULL, char_type, 4096);
+
+ gcc_jit_function *test_fn =
+ gcc_jit_context_new_function (ctxt, NULL,
+ GCC_JIT_FUNCTION_EXPORTED,
+ array_type,
+ "test_fn",
+ 0, NULL,
+ 0);
+ gcc_jit_lvalue *f =
+ gcc_jit_function_new_local (
+ test_fn,
+ NULL,
+ int_type, "f");
+
+ gcc_jit_block *block = gcc_jit_function_new_block (test_fn, NULL);
+
+ gcc_jit_block_end_with_return (
+ block, NULL,
+ gcc_jit_context_new_bitcast (ctxt, NULL,
+ gcc_jit_lvalue_as_rvalue (f),
+ array_type));
+}
+
+void
+verify_code (gcc_jit_context *ctxt, gcc_jit_result *result)
+{
+ CHECK_VALUE (result, NULL);
+
+ /* Verify that the correct error message was emitted. */
+ CHECK_STRING_VALUE (gcc_jit_context_get_first_error (ctxt),
+ "bitcast with types of different sizes");
+}
+
diff --git a/gcc/toplev.cc b/gcc/toplev.cc
index 534da1462e8..bc4921974eb 100644
--- a/gcc/toplev.cc
+++ b/gcc/toplev.cc
@@ -2368,6 +2368,7 @@ toplev::finalize (void)
gcse_c_finalize ();
ipa_cp_c_finalize ();
ira_costs_c_finalize ();
+ tree_cc_finalize ();
/* save_decoded_options uses opts_obstack, so these must
be cleaned up together. */
diff --git a/gcc/tree.cc b/gcc/tree.cc
index ae159ee20ce..fe9d9083026 100644
--- a/gcc/tree.cc
+++ b/gcc/tree.cc
@@ -6963,6 +6963,15 @@ build_reference_type (tree to_type)
(HOST_BITS_PER_WIDE_INT > 64 ? HOST_BITS_PER_WIDE_INT : 64)
static GTY(()) tree nonstandard_integer_type_cache[2 * MAX_INT_CACHED_PREC + 2];
+static void
+clear_nonstandard_integer_type_cache (void)
+{
+ for (size_t i = 0 ; i < 2 * MAX_INT_CACHED_PREC + 2 ; i++)
+ {
+ nonstandard_integer_type_cache[i] = NULL;
+ }
+}
+
/* Builds a signed or unsigned integer type of precision PRECISION.
Used for C bitfields whose precision does not match that of
built-in target types. */
@@ -14565,6 +14574,12 @@ get_attr_nonstring_decl (tree expr, tree *ref)
return NULL_TREE;
}
+void
+tree_cc_finalize (void)
+{
+ clear_nonstandard_integer_type_cache ();
+}
+
#if CHECKING_P
namespace selftest {
diff --git a/gcc/tree.h b/gcc/tree.h
index 30bc53c2996..bf886fc2472 100644
--- a/gcc/tree.h
+++ b/gcc/tree.h
@@ -5385,6 +5385,7 @@ extern bool real_minus_onep (const_tree);
extern void init_ttree (void);
extern void build_common_tree_nodes (bool);
extern void build_common_builtin_nodes (void);
+extern void tree_cc_finalize (void);
extern tree build_nonstandard_integer_type (unsigned HOST_WIDE_INT, int);
extern tree build_nonstandard_boolean_type (unsigned HOST_WIDE_INT);
extern tree build_range_type (tree, tree, tree);
--
2.26.2.7.g19db9cfb68.dirty
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH] libgccjit: Add support for bitcasts [PR104071]
2022-01-21 23:41 ` Antoni Boucher
@ 2022-04-08 19:22 ` David Malcolm
2022-04-09 18:05 ` Antoni Boucher
0 siblings, 1 reply; 7+ messages in thread
From: David Malcolm @ 2022-04-08 19:22 UTC (permalink / raw)
To: Antoni Boucher, gcc-patches, jit
On Fri, 2022-01-21 at 18:41 -0500, Antoni Boucher wrote:
> Hi.
> Here's the updated patch.
>
Thanks. Review below:
[...snip...]
> diff --git a/gcc/jit/libgccjit.cc b/gcc/jit/libgccjit.cc
> index 4c352e8c93d..6bf1e1ceee0 100644
> --- a/gcc/jit/libgccjit.cc
> +++ b/gcc/jit/libgccjit.cc
> @@ -2405,6 +2405,34 @@ gcc_jit_context_new_cast (gcc_jit_context *ctxt,
> return static_cast <gcc_jit_rvalue *> (ctxt->new_cast (loc, rvalue, type));
> }
>
> +/* Public entrypoint. See description in libgccjit.h.
> +
> + After error-checking, the real work is done by the
> + gcc::jit::recording::context::new_bitcast method in jit-recording.c. */
> +
> +gcc_jit_rvalue *
> +gcc_jit_context_new_bitcast (gcc_jit_context *ctxt,
> + gcc_jit_location *loc,
> + gcc_jit_rvalue *rvalue,
> + gcc_jit_type *type)
> +{
> + RETURN_NULL_IF_FAIL (ctxt, NULL, loc, "NULL context");
> + JIT_LOG_FUNC (ctxt->get_logger ());
> + /* LOC can be NULL. */
> + RETURN_NULL_IF_FAIL (rvalue, ctxt, loc, "NULL rvalue");
> + RETURN_NULL_IF_FAIL (type, ctxt, loc, "NULL type");
> + // TODO: check the sizes.
> + /*RETURN_NULL_IF_FAIL_PRINTF3 (
> + is_valid_cast (rvalue->get_type (), type),
> + ctxt, loc,
> + "cannot cast %s from type: %s to type: %s",
> + rvalue->get_debug_string (),
> + rvalue->get_type ()->get_debug_string (),
> + type->get_debug_string ());*/
I think we agreed that we can't check the sizes at this point, so this
commented-out check would be better replaced with a comment explaining
that we have to defer the check to playback time, when we have the
trees.
> +
> + return static_cast <gcc_jit_rvalue *> (ctxt->new_bitcast (loc, rvalue, type));
> +}
> +
> /* Public entrypoint. See description in libgccjit.h.
>
> After error-checking, the real work is done by the
[...snip...]
> diff --git a/gcc/testsuite/jit.dg/test-bitcast.c b/gcc/testsuite/jit.dg/test-bitcast.c
> new file mode 100644
> index 00000000000..a092fa117e6
> --- /dev/null
> +++ b/gcc/testsuite/jit.dg/test-bitcast.c
> @@ -0,0 +1,60 @@
> +#include <stdlib.h>
> +#include <stdio.h>
> +#include <string.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:
> +int
> +my_bitcast (double x)
> +{
> + return bitcast(x, int);
> +}
> + */
> + gcc_jit_type *int_type =
> + gcc_jit_context_get_int_type (ctxt, 4, 1);
> + gcc_jit_type *float_type =
> + gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_FLOAT);
This uses GCC_JIT_TYPE_FLOAT for the param...
> +
> + gcc_jit_param *x =
> + gcc_jit_context_new_param (
> + ctxt,
> + NULL,
> + float_type, "x");
> + gcc_jit_param *params[1] = {x};
> + gcc_jit_function *func =
> + gcc_jit_context_new_function (ctxt,
> + NULL,
> + GCC_JIT_FUNCTION_EXPORTED,
> + int_type,
> + "my_bitcast",
> + 1, params, 0);
[..snip...]
> +
> +void
> +verify_code (gcc_jit_context *ctxt, gcc_jit_result *result)
> +{
> + typedef int (*my_bitcast_fn_type) (double);
...but this uses "double". Presumably these should agree, and have the
same sizeof as the integer type.
> + CHECK_NON_NULL (result);
> + my_bitcast_fn_type my_bitcast =
> + (my_bitcast_fn_type)gcc_jit_result_get_code (result, "my_bitcast");
> + CHECK_NON_NULL (my_bitcast);
> + int val = my_bitcast (-5.1298714);
> + note ("my_bitcast returned: %d", val);
> + CHECK_VALUE (val, 35569201);
Out of curiosity, is there any particular significance for these
values? FWIW I rather like:
http://evanw.github.io/float-toy/
for directly manipulating the bits of floating point numbers.
[...snip...]
> diff --git a/gcc/toplev.cc b/gcc/toplev.cc
> index 534da1462e8..bc4921974eb 100644
> --- a/gcc/toplev.cc
> +++ b/gcc/toplev.cc
> @@ -2368,6 +2368,7 @@ toplev::finalize (void)
> gcse_c_finalize ();
> ipa_cp_c_finalize ();
> ira_costs_c_finalize ();
> + tree_cc_finalize ();
>
> /* save_decoded_options uses opts_obstack, so these must
> be cleaned up together. */
> diff --git a/gcc/tree.cc b/gcc/tree.cc
> index ae159ee20ce..fe9d9083026 100644
> --- a/gcc/tree.cc
> +++ b/gcc/tree.cc
> @@ -6963,6 +6963,15 @@ build_reference_type (tree to_type)
> (HOST_BITS_PER_WIDE_INT > 64 ? HOST_BITS_PER_WIDE_INT : 64)
> static GTY(()) tree nonstandard_integer_type_cache[2 * MAX_INT_CACHED_PREC + 2];
>
> +static void
> +clear_nonstandard_integer_type_cache (void)
> +{
> + for (size_t i = 0 ; i < 2 * MAX_INT_CACHED_PREC + 2 ; i++)
> + {
> + nonstandard_integer_type_cache[i] = NULL;
> + }
> +}
> +
> /* Builds a signed or unsigned integer type of precision PRECISION.
> Used for C bitfields whose precision does not match that of
> built-in target types. */
> @@ -14565,6 +14574,12 @@ get_attr_nonstring_decl (tree expr, tree *ref)
> return NULL_TREE;
> }
>
> +void
> +tree_cc_finalize (void)
> +{
> + clear_nonstandard_integer_type_cache ();
> +}
> +
> #if CHECKING_P
>
> namespace selftest {
> diff --git a/gcc/tree.h b/gcc/tree.h
> index 30bc53c2996..bf886fc2472 100644
> --- a/gcc/tree.h
> +++ b/gcc/tree.h
> @@ -5385,6 +5385,7 @@ extern bool real_minus_onep (const_tree);
> extern void init_ttree (void);
> extern void build_common_tree_nodes (bool);
> extern void build_common_builtin_nodes (void);
> +extern void tree_cc_finalize (void);
> extern tree build_nonstandard_integer_type (unsigned HOST_WIDE_INT, int);
> extern tree build_nonstandard_boolean_type (unsigned HOST_WIDE_INT);
> extern tree build_range_type (tree, tree, tree);
Looks OK to me, but am not officially a maintainer of these parts.
LGTM with those nits fixed - for next stage 1, or for trunk now if the
release maintainers are OK with it.
Thanks again for the patch, and sorry about the belated review.
Dave
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH] libgccjit: Add support for bitcasts [PR104071]
2022-04-08 19:22 ` David Malcolm
@ 2022-04-09 18:05 ` Antoni Boucher
2022-04-12 21:39 ` David Malcolm
0 siblings, 1 reply; 7+ messages in thread
From: Antoni Boucher @ 2022-04-09 18:05 UTC (permalink / raw)
To: David Malcolm, gcc-patches, jit
[-- Attachment #1: Type: text/plain, Size: 7272 bytes --]
Here's the updated patch.
On Fri, 2022-04-08 at 15:22 -0400, David Malcolm wrote:
> On Fri, 2022-01-21 at 18:41 -0500, Antoni Boucher wrote:
> > Hi.
> > Here's the updated patch.
> >
>
> Thanks. Review below:
>
> [...snip...]
>
> > diff --git a/gcc/jit/libgccjit.cc b/gcc/jit/libgccjit.cc
> > index 4c352e8c93d..6bf1e1ceee0 100644
> > --- a/gcc/jit/libgccjit.cc
> > +++ b/gcc/jit/libgccjit.cc
> > @@ -2405,6 +2405,34 @@ gcc_jit_context_new_cast (gcc_jit_context
> > *ctxt,
> > return static_cast <gcc_jit_rvalue *> (ctxt->new_cast (loc,
> > rvalue, type));
> > }
> >
> > +/* Public entrypoint. See description in libgccjit.h.
> > +
> > + After error-checking, the real work is done by the
> > + gcc::jit::recording::context::new_bitcast method in jit-
> > recording.c. */
> > +
> > +gcc_jit_rvalue *
> > +gcc_jit_context_new_bitcast (gcc_jit_context *ctxt,
> > + gcc_jit_location *loc,
> > + gcc_jit_rvalue *rvalue,
> > + gcc_jit_type *type)
> > +{
> > + RETURN_NULL_IF_FAIL (ctxt, NULL, loc, "NULL context");
> > + JIT_LOG_FUNC (ctxt->get_logger ());
> > + /* LOC can be NULL. */
> > + RETURN_NULL_IF_FAIL (rvalue, ctxt, loc, "NULL rvalue");
> > + RETURN_NULL_IF_FAIL (type, ctxt, loc, "NULL type");
> > + // TODO: check the sizes.
> > + /*RETURN_NULL_IF_FAIL_PRINTF3 (
> > + is_valid_cast (rvalue->get_type (), type),
> > + ctxt, loc,
> > + "cannot cast %s from type: %s to type: %s",
> > + rvalue->get_debug_string (),
> > + rvalue->get_type ()->get_debug_string (),
> > + type->get_debug_string ());*/
>
> I think we agreed that we can't check the sizes at this point, so
> this
> commented-out check would be better replaced with a comment
> explaining
> that we have to defer the check to playback time, when we have the
> trees.
>
> > +
> > + return static_cast <gcc_jit_rvalue *> (ctxt->new_bitcast (loc,
> > rvalue, type));
> > +}
> > +
> > /* Public entrypoint. See description in libgccjit.h.
> >
> > After error-checking, the real work is done by the
>
> [...snip...]
>
> > diff --git a/gcc/testsuite/jit.dg/test-bitcast.c
> > b/gcc/testsuite/jit.dg/test-bitcast.c
> > new file mode 100644
> > index 00000000000..a092fa117e6
> > --- /dev/null
> > +++ b/gcc/testsuite/jit.dg/test-bitcast.c
> > @@ -0,0 +1,60 @@
> > +#include <stdlib.h>
> > +#include <stdio.h>
> > +#include <string.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:
> > +int
> > +my_bitcast (double x)
> > +{
> > + return bitcast(x, int);
> > +}
> > + */
> > + gcc_jit_type *int_type =
> > + gcc_jit_context_get_int_type (ctxt, 4, 1);
> > + gcc_jit_type *float_type =
> > + gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_FLOAT);
>
> This uses GCC_JIT_TYPE_FLOAT for the param...
>
> > +
> > + gcc_jit_param *x =
> > + gcc_jit_context_new_param (
> > + ctxt,
> > + NULL,
> > + float_type, "x");
> > + gcc_jit_param *params[1] = {x};
> > + gcc_jit_function *func =
> > + gcc_jit_context_new_function (ctxt,
> > + NULL,
> > + GCC_JIT_FUNCTION_EXPORTED,
> > + int_type,
> > + "my_bitcast",
> > + 1, params, 0);
>
> [..snip...]
>
> > +
> > +void
> > +verify_code (gcc_jit_context *ctxt, gcc_jit_result *result)
> > +{
> > + typedef int (*my_bitcast_fn_type) (double);
>
> ...but this uses "double". Presumably these should agree, and have
> the
> same sizeof as the integer type.
>
> > + CHECK_NON_NULL (result);
> > + my_bitcast_fn_type my_bitcast =
> > + (my_bitcast_fn_type)gcc_jit_result_get_code (result,
> > "my_bitcast");
> > + CHECK_NON_NULL (my_bitcast);
> > + int val = my_bitcast (-5.1298714);
> > + note ("my_bitcast returned: %d", val);
> > + CHECK_VALUE (val, 35569201);
>
> Out of curiosity, is there any particular significance for these
> values? FWIW I rather like:
> http://evanw.github.io/float-toy/
> for directly manipulating the bits of floating point numbers.
The given float values, when bitcast to an int, gives the given int
value.
>
>
> [...snip...]
>
> > diff --git a/gcc/toplev.cc b/gcc/toplev.cc
> > index 534da1462e8..bc4921974eb 100644
> > --- a/gcc/toplev.cc
> > +++ b/gcc/toplev.cc
> > @@ -2368,6 +2368,7 @@ toplev::finalize (void)
> > gcse_c_finalize ();
> > ipa_cp_c_finalize ();
> > ira_costs_c_finalize ();
> > + tree_cc_finalize ();
> >
> > /* save_decoded_options uses opts_obstack, so these must
> > be cleaned up together. */
> > diff --git a/gcc/tree.cc b/gcc/tree.cc
> > index ae159ee20ce..fe9d9083026 100644
> > --- a/gcc/tree.cc
> > +++ b/gcc/tree.cc
> > @@ -6963,6 +6963,15 @@ build_reference_type (tree to_type)
> > (HOST_BITS_PER_WIDE_INT > 64 ? HOST_BITS_PER_WIDE_INT : 64)
> > static GTY(()) tree nonstandard_integer_type_cache[2 *
> > MAX_INT_CACHED_PREC + 2];
> >
> > +static void
> > +clear_nonstandard_integer_type_cache (void)
> > +{
> > + for (size_t i = 0 ; i < 2 * MAX_INT_CACHED_PREC + 2 ; i++)
> > + {
> > + nonstandard_integer_type_cache[i] = NULL;
> > + }
> > +}
> > +
> > /* Builds a signed or unsigned integer type of precision
> > PRECISION.
> > Used for C bitfields whose precision does not match that of
> > built-in target types. */
> > @@ -14565,6 +14574,12 @@ get_attr_nonstring_decl (tree expr, tree
> > *ref)
> > return NULL_TREE;
> > }
> >
> > +void
> > +tree_cc_finalize (void)
> > +{
> > + clear_nonstandard_integer_type_cache ();
> > +}
> > +
> > #if CHECKING_P
> >
> > namespace selftest {
> > diff --git a/gcc/tree.h b/gcc/tree.h
> > index 30bc53c2996..bf886fc2472 100644
> > --- a/gcc/tree.h
> > +++ b/gcc/tree.h
> > @@ -5385,6 +5385,7 @@ extern bool real_minus_onep (const_tree);
> > extern void init_ttree (void);
> > extern void build_common_tree_nodes (bool);
> > extern void build_common_builtin_nodes (void);
> > +extern void tree_cc_finalize (void);
> > extern tree build_nonstandard_integer_type (unsigned
> > HOST_WIDE_INT, int);
> > extern tree build_nonstandard_boolean_type (unsigned
> > HOST_WIDE_INT);
> > extern tree build_range_type (tree, tree, tree);
>
> Looks OK to me, but am not officially a maintainer of these parts.
>
> LGTM with those nits fixed - for next stage 1, or for trunk now if
> the
> release maintainers are OK with it.
>
> Thanks again for the patch, and sorry about the belated review.
>
> Dave
>
>
>
[-- Attachment #2: 0001-libgccjit-Add-support-for-bitcasts-PR104071.patch --]
[-- Type: text/x-patch, Size: 20644 bytes --]
From 195879c135925a2bc2d53374716dc4b57c79d843 Mon Sep 17 00:00:00 2001
From: Antoni Boucher <bouanto@zoho.com>
Date: Wed, 9 Jun 2021 18:29:14 -0400
Subject: [PATCH] libgccjit: Add support for bitcasts [PR104071]
2022-04-09 Antoni Boucher <bouanto@zoho.com>
gcc/jit/
PR jit/104071
* docs/topics/compatibility.rst (LIBGCCJIT_ABI_21): New ABI tag.
* docs/topics/expressions.rst: Add documentation for the
function gcc_jit_context_new_bitcast.
* jit-playback.cc: New function (new_bitcast).
* jit-playback.h: New function (new_bitcast).
* jit-recording.cc: New functions (new_bitcast,
bitcast::replay_into, bitcast::visit_children,
bitcast::make_debug_string, bitcast::write_reproducer).
* jit-recording.h: New class (bitcast) and new function
(new_bitcast, bitcast::replay_into, bitcast::visit_children,
bitcast::make_debug_string, bitcast::write_reproducer,
bitcast::get_precedence).
* libgccjit.cc: New function (gcc_jit_context_new_bitcast)
* libgccjit.h: New function (gcc_jit_context_new_bitcast)
* libgccjit.map (LIBGCCJIT_ABI_21): New ABI tag.
gcc/testsuite/
PR jit/104071
* jit.dg/all-non-failing-tests.h: Add new test-bitcast.
* jit.dg/test-bitcast.c: New test.
* jit.dg/test-error-bad-bitcast.c: New test.
* jit.dg/test-error-bad-bitcast2.c: New test.
gcc/
PR jit/104071
* toplev.cc: Call the new function tree_cc_finalize in
toplev::finalize.
* tree.cc: New functions (clear_nonstandard_integer_type_cache
and tree_cc_finalize) to clear the cache of non-standard integer
types to avoid having issues with some optimizations of
bitcast where the SSA_NAME will have a size of a cached
integer type that should have been invalidated, causing a
comparison of integer constant to fail.
* tree.h: New function (tree_cc_finalize).
---
gcc/jit/docs/topics/compatibility.rst | 9 +++
gcc/jit/docs/topics/expressions.rst | 19 ++++++
gcc/jit/jit-playback.cc | 27 ++++++++
gcc/jit/jit-playback.h | 5 ++
gcc/jit/jit-recording.cc | 66 +++++++++++++++++++
gcc/jit/jit-recording.h | 32 +++++++++
gcc/jit/libgccjit.cc | 22 +++++++
gcc/jit/libgccjit.h | 15 +++++
gcc/jit/libgccjit.map | 9 +++
gcc/testsuite/jit.dg/all-non-failing-tests.h | 10 +++
gcc/testsuite/jit.dg/test-bitcast.c | 60 +++++++++++++++++
gcc/testsuite/jit.dg/test-error-bad-bitcast.c | 62 +++++++++++++++++
.../jit.dg/test-error-bad-bitcast2.c | 62 +++++++++++++++++
gcc/toplev.cc | 1 +
gcc/tree.cc | 15 +++++
gcc/tree.h | 1 +
16 files changed, 415 insertions(+)
create mode 100644 gcc/testsuite/jit.dg/test-bitcast.c
create mode 100644 gcc/testsuite/jit.dg/test-error-bad-bitcast.c
create mode 100644 gcc/testsuite/jit.dg/test-error-bad-bitcast2.c
diff --git a/gcc/jit/docs/topics/compatibility.rst b/gcc/jit/docs/topics/compatibility.rst
index 16cebe31a10..610d9dc175f 100644
--- a/gcc/jit/docs/topics/compatibility.rst
+++ b/gcc/jit/docs/topics/compatibility.rst
@@ -302,3 +302,12 @@ thread-local storage model of a variable:
section of a variable:
* :func:`gcc_jit_lvalue_set_link_section`
+
+.. _LIBGCCJIT_ABI_21:
+
+``LIBGCCJIT_ABI_21``
+-----------------------
+``LIBGCCJIT_ABI_21`` covers the addition of an API entrypoint to bitcast a
+value from one type to another:
+
+ * :func:`gcc_jit_context_new_bitcast`
diff --git a/gcc/jit/docs/topics/expressions.rst b/gcc/jit/docs/topics/expressions.rst
index 791a20398ca..e0b6f426aee 100644
--- a/gcc/jit/docs/topics/expressions.rst
+++ b/gcc/jit/docs/topics/expressions.rst
@@ -649,6 +649,25 @@ Type-coercion
* int <-> bool
* P* <-> Q*, for pointer types P and Q
+.. function:: gcc_jit_rvalue *\
+ gcc_jit_context_new_bitcast (gcc_jit_context *ctxt,\
+ gcc_jit_location *loc,\
+ gcc_jit_rvalue *rvalue,\
+ gcc_jit_type *type)
+
+ Given an rvalue of T, bitcast it to another type, meaning that this will
+ generate a new rvalue by interpreting the bits of ``rvalue`` to the layout
+ of ``type``.
+
+ The type of rvalue must be the same size as the size of ``type``.
+
+ This entrypoint was added in :ref:`LIBGCCJIT_ABI_21`; you can test for
+ its presence using
+
+ .. code-block:: c
+
+ #ifdef LIBGCCJIT_HAVE_gcc_jit_context_new_bitcast
+
Lvalues
-------
diff --git a/gcc/jit/jit-playback.cc b/gcc/jit/jit-playback.cc
index d1835c79863..d2efae1c163 100644
--- a/gcc/jit/jit-playback.cc
+++ b/gcc/jit/jit-playback.cc
@@ -1390,6 +1390,33 @@ new_cast (playback::location *loc,
return new rvalue (this, t_cast);
}
+playback::rvalue *
+playback::context::
+new_bitcast (location *loc,
+ rvalue *expr,
+ type *type_)
+{
+ tree expr_size = TYPE_SIZE (expr->get_type ()->as_tree ());
+ tree type_size = TYPE_SIZE (type_->as_tree ());
+ tree t_expr = expr->as_tree ();
+ tree t_dst_type = type_->as_tree ();
+ if (expr_size != type_size)
+ {
+ active_playback_ctxt->add_error (loc,
+ "bitcast with types of different sizes");
+ fprintf (stderr, "input expression (size: %ld):\n",
+ tree_to_uhwi (expr_size));
+ debug_tree (t_expr);
+ fprintf (stderr, "requested type (size: %ld):\n",
+ tree_to_uhwi (type_size));
+ debug_tree (t_dst_type);
+ }
+ tree t_bitcast = build1 (VIEW_CONVERT_EXPR, t_dst_type, t_expr);
+ if (loc)
+ set_tree_location (t_bitcast, loc);
+ return new rvalue (this, t_bitcast);
+}
+
/* Construct a playback::lvalue instance (wrapping a tree) for an
array access. */
diff --git a/gcc/jit/jit-playback.h b/gcc/jit/jit-playback.h
index c93d7055d43..5b107be9d69 100644
--- a/gcc/jit/jit-playback.h
+++ b/gcc/jit/jit-playback.h
@@ -180,6 +180,11 @@ public:
rvalue *expr,
type *type_);
+ rvalue *
+ new_bitcast (location *loc,
+ rvalue *expr,
+ type *type_);
+
lvalue *
new_array_access (location *loc,
rvalue *ptr,
diff --git a/gcc/jit/jit-recording.cc b/gcc/jit/jit-recording.cc
index 1e3fadfacd7..e1029086da8 100644
--- a/gcc/jit/jit-recording.cc
+++ b/gcc/jit/jit-recording.cc
@@ -1242,6 +1242,22 @@ recording::context::new_cast (recording::location *loc,
return result;
}
+/* Create a recording::bitcast instance and add it to this context's list
+ of mementos.
+
+ Implements the post-error-checking part of
+ gcc_jit_context_new_bitcast. */
+
+recording::rvalue *
+recording::context::new_bitcast (location *loc,
+ rvalue *expr,
+ type *type_)
+{
+ recording::rvalue *result = new bitcast (this, loc, expr, type_);
+ record (result);
+ return result;
+}
+
/* Create a recording::call instance and add it to this context's list
of mementos.
@@ -5740,6 +5756,56 @@ recording::cast::write_reproducer (reproducer &r)
r.get_identifier_as_type (get_type ()));
}
+/* Implementation of pure virtual hook recording::memento::replay_into
+ for recording::bitcast. */
+
+void
+recording::bitcast::replay_into (replayer *r)
+{
+ set_playback_obj (r->new_bitcast (playback_location (r, m_loc),
+ m_rvalue->playback_rvalue (),
+ get_type ()->playback_type ()));
+}
+
+/* Implementation of pure virtual hook recording::rvalue::visit_children
+ for recording::bitcast. */
+void
+recording::bitcast::visit_children (rvalue_visitor *v)
+{
+ v->visit (m_rvalue);
+}
+
+/* Implementation of recording::memento::make_debug_string for
+ casts. */
+
+recording::string *
+recording::bitcast::make_debug_string ()
+{
+ enum precedence prec = get_precedence ();
+ return string::from_printf (m_ctxt,
+ "bitcast(%s, %s)",
+ m_rvalue->get_debug_string_parens (prec),
+ get_type ()->get_debug_string ());
+}
+
+/* Implementation of recording::memento::write_reproducer for casts. */
+
+void
+recording::bitcast::write_reproducer (reproducer &r)
+{
+ const char *id = r.make_identifier (this, "rvalue");
+ r.write (" gcc_jit_rvalue *%s =\n"
+ " gcc_jit_context_new_bitcast (%s,\n"
+ " %s, /* gcc_jit_location *loc */\n"
+ " %s, /* gcc_jit_rvalue *rvalue */\n"
+ " %s); /* gcc_jit_type *type */\n",
+ id,
+ r.get_identifier (get_context ()),
+ r.get_identifier (m_loc),
+ r.get_identifier_as_rvalue (m_rvalue),
+ r.get_identifier_as_type (get_type ()));
+}
+
/* The implementation of class gcc::jit::recording::base_call. */
/* The constructor for gcc::jit::recording::base_call. */
diff --git a/gcc/jit/jit-recording.h b/gcc/jit/jit-recording.h
index 846d65cb202..ed03b3a24c8 100644
--- a/gcc/jit/jit-recording.h
+++ b/gcc/jit/jit-recording.h
@@ -205,6 +205,11 @@ public:
rvalue *expr,
type *type_);
+ rvalue *
+ new_bitcast (location *loc,
+ rvalue *expr,
+ type *type_);
+
lvalue *
new_array_access (location *loc,
rvalue *ptr,
@@ -1691,6 +1696,33 @@ private:
rvalue *m_rvalue;
};
+class bitcast : public rvalue
+{
+public:
+ bitcast (context *ctxt,
+ location *loc,
+ rvalue *a,
+ type *type_)
+ : rvalue (ctxt, loc, type_),
+ m_rvalue (a)
+ {}
+
+ void replay_into (replayer *r) FINAL OVERRIDE;
+
+ void visit_children (rvalue_visitor *v) FINAL OVERRIDE;
+
+private:
+ string * make_debug_string () FINAL OVERRIDE;
+ void write_reproducer (reproducer &r) FINAL OVERRIDE;
+ enum precedence get_precedence () const FINAL OVERRIDE
+ {
+ return PRECEDENCE_CAST;
+ }
+
+private:
+ rvalue *m_rvalue;
+};
+
class base_call : public rvalue
{
public:
diff --git a/gcc/jit/libgccjit.cc b/gcc/jit/libgccjit.cc
index 4c352e8c93d..3535203975c 100644
--- a/gcc/jit/libgccjit.cc
+++ b/gcc/jit/libgccjit.cc
@@ -2405,6 +2405,28 @@ gcc_jit_context_new_cast (gcc_jit_context *ctxt,
return static_cast <gcc_jit_rvalue *> (ctxt->new_cast (loc, rvalue, type));
}
+/* Public entrypoint. See description in libgccjit.h.
+
+ After error-checking, the real work is done by the
+ gcc::jit::recording::context::new_bitcast method in jit-recording.c. */
+
+gcc_jit_rvalue *
+gcc_jit_context_new_bitcast (gcc_jit_context *ctxt,
+ gcc_jit_location *loc,
+ gcc_jit_rvalue *rvalue,
+ gcc_jit_type *type)
+{
+ RETURN_NULL_IF_FAIL (ctxt, NULL, loc, "NULL context");
+ JIT_LOG_FUNC (ctxt->get_logger ());
+ /* LOC can be NULL. */
+ RETURN_NULL_IF_FAIL (rvalue, ctxt, loc, "NULL rvalue");
+ RETURN_NULL_IF_FAIL (type, ctxt, loc, "NULL type");
+ /* We cannot check if the size of rvalue matches the size of type here, so
+ we'll do it at playback. */
+
+ return static_cast <gcc_jit_rvalue *> (ctxt->new_bitcast (loc, rvalue, type));
+}
+
/* Public entrypoint. See description in libgccjit.h.
After error-checking, the real work is done by the
diff --git a/gcc/jit/libgccjit.h b/gcc/jit/libgccjit.h
index 2a5ffacb1fe..960e4f4261e 100644
--- a/gcc/jit/libgccjit.h
+++ b/gcc/jit/libgccjit.h
@@ -1206,6 +1206,21 @@ gcc_jit_context_new_cast (gcc_jit_context *ctxt,
gcc_jit_rvalue *rvalue,
gcc_jit_type *type);
+/* Reinterpret a value as another type.
+
+#define LIBGCCJIT_HAVE_gcc_jit_context_new_bitcast
+
+ The types must be of the same size.
+
+ This API entrypoint was added in LIBGCCJIT_ABI_21; you can test for its
+ presence using
+ #ifdef LIBGCCJIT_HAVE_gcc_jit_context_new_bitcast */
+extern gcc_jit_rvalue *
+gcc_jit_context_new_bitcast (gcc_jit_context *ctxt,
+ gcc_jit_location *loc,
+ gcc_jit_rvalue *rvalue,
+ gcc_jit_type *type);
+
extern gcc_jit_lvalue *
gcc_jit_context_new_array_access (gcc_jit_context *ctxt,
gcc_jit_location *loc,
diff --git a/gcc/jit/libgccjit.map b/gcc/jit/libgccjit.map
index f373fd39ac7..38c355437bf 100644
--- a/gcc/jit/libgccjit.map
+++ b/gcc/jit/libgccjit.map
@@ -238,8 +238,17 @@ LIBGCCJIT_ABI_18 {
} LIBGCCJIT_ABI_17;
LIBGCCJIT_ABI_19 {
+ global:
gcc_jit_context_new_array_constructor;
gcc_jit_context_new_struct_constructor;
gcc_jit_context_new_union_constructor;
gcc_jit_global_set_initializer_rvalue;
} LIBGCCJIT_ABI_18;
+
+LIBGCCJIT_ABI_20 {
+} LIBGCCJIT_ABI_19;
+
+LIBGCCJIT_ABI_21 {
+ global:
+ gcc_jit_context_new_bitcast;
+} LIBGCCJIT_ABI_20;
diff --git a/gcc/testsuite/jit.dg/all-non-failing-tests.h b/gcc/testsuite/jit.dg/all-non-failing-tests.h
index 29afe064db6..656351edce1 100644
--- a/gcc/testsuite/jit.dg/all-non-failing-tests.h
+++ b/gcc/testsuite/jit.dg/all-non-failing-tests.h
@@ -77,6 +77,13 @@
/* test-builtin-unreachable.c: We don't add this one, since it touches
the optimization level of the context as a whole. */
+/* test-bitcast.c */
+#define create_code create_code_bitcast
+#define verify_code verify_code_bitcast
+#include "test-bitcast.c"
+#undef create_code
+#undef verify_code
+
/* test-calling-external-function.c */
#define create_code create_code_calling_external_function
#define verify_code verify_code_calling_external_function
@@ -400,6 +407,9 @@ const struct testcase testcases[] = {
{"builtin-memcpy",
create_code_builtin_memcpy,
verify_code_builtin_memcpy},
+ {"bitcast",
+ create_code_bitcast,
+ verify_code_bitcast},
{"calling_external_function",
create_code_calling_external_function,
verify_code_calling_external_function},
diff --git a/gcc/testsuite/jit.dg/test-bitcast.c b/gcc/testsuite/jit.dg/test-bitcast.c
new file mode 100644
index 00000000000..16d889d3abe
--- /dev/null
+++ b/gcc/testsuite/jit.dg/test-bitcast.c
@@ -0,0 +1,60 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.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:
+int
+my_bitcast (float x)
+{
+ return bitcast(x, int);
+}
+ */
+ gcc_jit_type *int_type =
+ gcc_jit_context_get_int_type (ctxt, 4, 1);
+ gcc_jit_type *float_type =
+ gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_FLOAT);
+
+ gcc_jit_param *x =
+ gcc_jit_context_new_param (
+ ctxt,
+ NULL,
+ float_type, "x");
+ gcc_jit_param *params[1] = {x};
+ gcc_jit_function *func =
+ gcc_jit_context_new_function (ctxt,
+ NULL,
+ GCC_JIT_FUNCTION_EXPORTED,
+ int_type,
+ "my_bitcast",
+ 1, params, 0);
+
+ gcc_jit_block *initial =
+ gcc_jit_function_new_block (func, "initial");
+
+ gcc_jit_block_end_with_return(initial, NULL,
+ gcc_jit_context_new_bitcast(ctxt,
+ NULL,
+ gcc_jit_param_as_rvalue(x),
+ int_type
+ ));
+}
+
+void
+verify_code (gcc_jit_context *ctxt, gcc_jit_result *result)
+{
+ typedef int (*my_bitcast_fn_type) (float);
+ CHECK_NON_NULL (result);
+ my_bitcast_fn_type my_bitcast =
+ (my_bitcast_fn_type)gcc_jit_result_get_code (result, "my_bitcast");
+ CHECK_NON_NULL (my_bitcast);
+ int val = my_bitcast (-5.1298714);
+ note ("my_bitcast returned: %d", val);
+ CHECK_VALUE (val, 35569201);
+}
diff --git a/gcc/testsuite/jit.dg/test-error-bad-bitcast.c b/gcc/testsuite/jit.dg/test-error-bad-bitcast.c
new file mode 100644
index 00000000000..642890605ad
--- /dev/null
+++ b/gcc/testsuite/jit.dg/test-error-bad-bitcast.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:
+
+ int
+ test_fn ()
+ {
+ char f[4096];
+ return bitcast(f, int);
+ }
+
+ and verify that the API complains about the bad cast.
+ */
+ gcc_jit_type *int_type =
+ gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_INT);
+ gcc_jit_type *char_type =
+ gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_CHAR);
+
+
+ gcc_jit_type *array_type =
+ gcc_jit_context_new_array_type (ctxt, NULL, char_type, 4096);
+
+ gcc_jit_function *test_fn =
+ gcc_jit_context_new_function (ctxt, NULL,
+ GCC_JIT_FUNCTION_EXPORTED,
+ int_type,
+ "test_fn",
+ 0, NULL,
+ 0);
+ gcc_jit_lvalue *f =
+ gcc_jit_function_new_local (
+ test_fn,
+ NULL,
+ array_type, "f");
+
+ gcc_jit_block *block = gcc_jit_function_new_block (test_fn, NULL);
+
+ gcc_jit_block_end_with_return (
+ block, NULL,
+ gcc_jit_context_new_bitcast (ctxt, NULL,
+ gcc_jit_lvalue_as_rvalue (f),
+ int_type));
+}
+
+void
+verify_code (gcc_jit_context *ctxt, gcc_jit_result *result)
+{
+ CHECK_VALUE (result, NULL);
+
+ /* Verify that the correct error message was emitted. */
+ CHECK_STRING_VALUE (gcc_jit_context_get_first_error (ctxt),
+ "bitcast with types of different sizes");
+}
+
diff --git a/gcc/testsuite/jit.dg/test-error-bad-bitcast2.c b/gcc/testsuite/jit.dg/test-error-bad-bitcast2.c
new file mode 100644
index 00000000000..602ae407076
--- /dev/null
+++ b/gcc/testsuite/jit.dg/test-error-bad-bitcast2.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:
+
+ char[4096]
+ test_fn ()
+ {
+ int f;
+ return bitcast(f, char[4096]);
+ }
+
+ and verify that the API complains about the bad cast.
+ */
+ gcc_jit_type *int_type =
+ gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_INT);
+ gcc_jit_type *char_type =
+ gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_CHAR);
+
+
+ gcc_jit_type *array_type =
+ gcc_jit_context_new_array_type (ctxt, NULL, char_type, 4096);
+
+ gcc_jit_function *test_fn =
+ gcc_jit_context_new_function (ctxt, NULL,
+ GCC_JIT_FUNCTION_EXPORTED,
+ array_type,
+ "test_fn",
+ 0, NULL,
+ 0);
+ gcc_jit_lvalue *f =
+ gcc_jit_function_new_local (
+ test_fn,
+ NULL,
+ int_type, "f");
+
+ gcc_jit_block *block = gcc_jit_function_new_block (test_fn, NULL);
+
+ gcc_jit_block_end_with_return (
+ block, NULL,
+ gcc_jit_context_new_bitcast (ctxt, NULL,
+ gcc_jit_lvalue_as_rvalue (f),
+ array_type));
+}
+
+void
+verify_code (gcc_jit_context *ctxt, gcc_jit_result *result)
+{
+ CHECK_VALUE (result, NULL);
+
+ /* Verify that the correct error message was emitted. */
+ CHECK_STRING_VALUE (gcc_jit_context_get_first_error (ctxt),
+ "bitcast with types of different sizes");
+}
+
diff --git a/gcc/toplev.cc b/gcc/toplev.cc
index 534da1462e8..bc4921974eb 100644
--- a/gcc/toplev.cc
+++ b/gcc/toplev.cc
@@ -2368,6 +2368,7 @@ toplev::finalize (void)
gcse_c_finalize ();
ipa_cp_c_finalize ();
ira_costs_c_finalize ();
+ tree_cc_finalize ();
/* save_decoded_options uses opts_obstack, so these must
be cleaned up together. */
diff --git a/gcc/tree.cc b/gcc/tree.cc
index ae159ee20ce..fe9d9083026 100644
--- a/gcc/tree.cc
+++ b/gcc/tree.cc
@@ -6963,6 +6963,15 @@ build_reference_type (tree to_type)
(HOST_BITS_PER_WIDE_INT > 64 ? HOST_BITS_PER_WIDE_INT : 64)
static GTY(()) tree nonstandard_integer_type_cache[2 * MAX_INT_CACHED_PREC + 2];
+static void
+clear_nonstandard_integer_type_cache (void)
+{
+ for (size_t i = 0 ; i < 2 * MAX_INT_CACHED_PREC + 2 ; i++)
+ {
+ nonstandard_integer_type_cache[i] = NULL;
+ }
+}
+
/* Builds a signed or unsigned integer type of precision PRECISION.
Used for C bitfields whose precision does not match that of
built-in target types. */
@@ -14565,6 +14574,12 @@ get_attr_nonstring_decl (tree expr, tree *ref)
return NULL_TREE;
}
+void
+tree_cc_finalize (void)
+{
+ clear_nonstandard_integer_type_cache ();
+}
+
#if CHECKING_P
namespace selftest {
diff --git a/gcc/tree.h b/gcc/tree.h
index 30bc53c2996..bf886fc2472 100644
--- a/gcc/tree.h
+++ b/gcc/tree.h
@@ -5385,6 +5385,7 @@ extern bool real_minus_onep (const_tree);
extern void init_ttree (void);
extern void build_common_tree_nodes (bool);
extern void build_common_builtin_nodes (void);
+extern void tree_cc_finalize (void);
extern tree build_nonstandard_integer_type (unsigned HOST_WIDE_INT, int);
extern tree build_nonstandard_boolean_type (unsigned HOST_WIDE_INT);
extern tree build_range_type (tree, tree, tree);
--
2.26.2.7.g19db9cfb68.dirty
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH] libgccjit: Add support for bitcasts [PR104071]
2022-04-09 18:05 ` Antoni Boucher
@ 2022-04-12 21:39 ` David Malcolm
0 siblings, 0 replies; 7+ messages in thread
From: David Malcolm @ 2022-04-12 21:39 UTC (permalink / raw)
To: Antoni Boucher, gcc-patches, jit
On Sat, 2022-04-09 at 14:05 -0400, Antoni Boucher wrote:
> Here's the updated patch.
Thanks.
I updated the patch somewhat:
* fixed up some hunks that didn't quite apply
* whitespace fixes
* added a missing comment
* regenerated .texinfo from .rst
* test-bitcast.c failed for me; the bitcast of -5.1298714 float to int
didn't give me the expected 35569201; I got this value:
(gdb) p val
$1 = -1062983704
(gdb) p /x val
$2 = 0xc0a427e8
(gdb) p /x 35569201
$3 = 0x21ebe31
and I couldn't figure out what the relationship between these two
values could be.
The expected: 35569201 == 0x21ebe31
0x021ebe31 as float is 1 × 2^-123 × 1.2401792 = 1.1662589e-37
I rewrote the test to explicitly use int32_t rather than int, but this
didn't help.
I wondered if this was an endianness issue, but:
-5.1298713 is -1 × 2^2 × 1.2824678, which is 0xc0a427e8
In the end, I changed the constants in the test to these:
(gdb) p *(float *)&val
$25 = 3.14159274
(gdb) p *(int32_t *)&val
$26 = 1078530011
(gdb) p /x *(int32_t *)&val
$27 = 0x40490fdb
which passes for me.
Successfully bootstrapped & regrtested on x86_64-pc-linux-gnu.
I've pushed the patch to trunk for GCC 12 as r12-8117-g30f7c83e9cfe7c
https://gcc.gnu.org/git/?p=gcc.git;a=commitdiff;h=30f7c83e9cfe7c015448d72f63c4c39d14bc6de6
Dave
>
> On Fri, 2022-04-08 at 15:22 -0400, David Malcolm wrote:
> > On Fri, 2022-01-21 at 18:41 -0500, Antoni Boucher wrote:
> > > Hi.
> > > Here's the updated patch.
> > >
> >
> > Thanks. Review below:
> >
> > [...snip...]
> >
> > > diff --git a/gcc/jit/libgccjit.cc b/gcc/jit/libgccjit.cc
> > > index 4c352e8c93d..6bf1e1ceee0 100644
> > > --- a/gcc/jit/libgccjit.cc
> > > +++ b/gcc/jit/libgccjit.cc
> > > @@ -2405,6 +2405,34 @@ gcc_jit_context_new_cast (gcc_jit_context
> > > *ctxt,
> > > return static_cast <gcc_jit_rvalue *> (ctxt->new_cast (loc,
> > > rvalue, type));
> > > }
> > >
> > > +/* Public entrypoint. See description in libgccjit.h.
> > > +
> > > + After error-checking, the real work is done by the
> > > + gcc::jit::recording::context::new_bitcast method in jit-
> > > recording.c. */
> > > +
> > > +gcc_jit_rvalue *
> > > +gcc_jit_context_new_bitcast (gcc_jit_context *ctxt,
> > > + gcc_jit_location *loc,
> > > + gcc_jit_rvalue *rvalue,
> > > + gcc_jit_type *type)
> > > +{
> > > + RETURN_NULL_IF_FAIL (ctxt, NULL, loc, "NULL context");
> > > + JIT_LOG_FUNC (ctxt->get_logger ());
> > > + /* LOC can be NULL. */
> > > + RETURN_NULL_IF_FAIL (rvalue, ctxt, loc, "NULL rvalue");
> > > + RETURN_NULL_IF_FAIL (type, ctxt, loc, "NULL type");
> > > + // TODO: check the sizes.
> > > + /*RETURN_NULL_IF_FAIL_PRINTF3 (
> > > + is_valid_cast (rvalue->get_type (), type),
> > > + ctxt, loc,
> > > + "cannot cast %s from type: %s to type: %s",
> > > + rvalue->get_debug_string (),
> > > + rvalue->get_type ()->get_debug_string (),
> > > + type->get_debug_string ());*/
> >
> > I think we agreed that we can't check the sizes at this point, so
> > this
> > commented-out check would be better replaced with a comment
> > explaining
> > that we have to defer the check to playback time, when we have the
> > trees.
> >
> > > +
> > > + return static_cast <gcc_jit_rvalue *> (ctxt->new_bitcast (loc,
> > > rvalue, type));
> > > +}
> > > +
> > > /* Public entrypoint. See description in libgccjit.h.
> > >
> > > After error-checking, the real work is done by the
> >
> > [...snip...]
> >
> > > diff --git a/gcc/testsuite/jit.dg/test-bitcast.c
> > > b/gcc/testsuite/jit.dg/test-bitcast.c
> > > new file mode 100644
> > > index 00000000000..a092fa117e6
> > > --- /dev/null
> > > +++ b/gcc/testsuite/jit.dg/test-bitcast.c
> > > @@ -0,0 +1,60 @@
> > > +#include <stdlib.h>
> > > +#include <stdio.h>
> > > +#include <string.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:
> > > +int
> > > +my_bitcast (double x)
> > > +{
> > > + return bitcast(x, int);
> > > +}
> > > + */
> > > + gcc_jit_type *int_type =
> > > + gcc_jit_context_get_int_type (ctxt, 4, 1);
> > > + gcc_jit_type *float_type =
> > > + gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_FLOAT);
> >
> > This uses GCC_JIT_TYPE_FLOAT for the param...
> >
> > > +
> > > + gcc_jit_param *x =
> > > + gcc_jit_context_new_param (
> > > + ctxt,
> > > + NULL,
> > > + float_type, "x");
> > > + gcc_jit_param *params[1] = {x};
> > > + gcc_jit_function *func =
> > > + gcc_jit_context_new_function (ctxt,
> > > + NULL,
> > > + GCC_JIT_FUNCTION_EXPORTED,
> > > + int_type,
> > > + "my_bitcast",
> > > + 1, params, 0);
> >
> > [..snip...]
> >
> > > +
> > > +void
> > > +verify_code (gcc_jit_context *ctxt, gcc_jit_result *result)
> > > +{
> > > + typedef int (*my_bitcast_fn_type) (double);
> >
> > ...but this uses "double". Presumably these should agree, and have
> > the
> > same sizeof as the integer type.
> >
> > > + CHECK_NON_NULL (result);
> > > + my_bitcast_fn_type my_bitcast =
> > > + (my_bitcast_fn_type)gcc_jit_result_get_code (result,
> > > "my_bitcast");
> > > + CHECK_NON_NULL (my_bitcast);
> > > + int val = my_bitcast (-5.1298714);
> > > + note ("my_bitcast returned: %d", val);
> > > + CHECK_VALUE (val, 35569201);
> >
> > Out of curiosity, is there any particular significance for these
> > values? FWIW I rather like:
> > http://evanw.github.io/float-toy/
> > for directly manipulating the bits of floating point numbers.
>
> The given float values, when bitcast to an int, gives the given int
> value.
>
> >
> >
> > [...snip...]
> >
> > > diff --git a/gcc/toplev.cc b/gcc/toplev.cc
> > > index 534da1462e8..bc4921974eb 100644
> > > --- a/gcc/toplev.cc
> > > +++ b/gcc/toplev.cc
> > > @@ -2368,6 +2368,7 @@ toplev::finalize (void)
> > > gcse_c_finalize ();
> > > ipa_cp_c_finalize ();
> > > ira_costs_c_finalize ();
> > > + tree_cc_finalize ();
> > >
> > > /* save_decoded_options uses opts_obstack, so these must
> > > be cleaned up together. */
> > > diff --git a/gcc/tree.cc b/gcc/tree.cc
> > > index ae159ee20ce..fe9d9083026 100644
> > > --- a/gcc/tree.cc
> > > +++ b/gcc/tree.cc
> > > @@ -6963,6 +6963,15 @@ build_reference_type (tree to_type)
> > > (HOST_BITS_PER_WIDE_INT > 64 ? HOST_BITS_PER_WIDE_INT : 64)
> > > static GTY(()) tree nonstandard_integer_type_cache[2 *
> > > MAX_INT_CACHED_PREC + 2];
> > >
> > > +static void
> > > +clear_nonstandard_integer_type_cache (void)
> > > +{
> > > + for (size_t i = 0 ; i < 2 * MAX_INT_CACHED_PREC + 2 ; i++)
> > > + {
> > > + nonstandard_integer_type_cache[i] = NULL;
> > > + }
> > > +}
> > > +
> > > /* Builds a signed or unsigned integer type of precision
> > > PRECISION.
> > > Used for C bitfields whose precision does not match that of
> > > built-in target types. */
> > > @@ -14565,6 +14574,12 @@ get_attr_nonstring_decl (tree expr, tree
> > > *ref)
> > > return NULL_TREE;
> > > }
> > >
> > > +void
> > > +tree_cc_finalize (void)
> > > +{
> > > + clear_nonstandard_integer_type_cache ();
> > > +}
> > > +
> > > #if CHECKING_P
> > >
> > > namespace selftest {
> > > diff --git a/gcc/tree.h b/gcc/tree.h
> > > index 30bc53c2996..bf886fc2472 100644
> > > --- a/gcc/tree.h
> > > +++ b/gcc/tree.h
> > > @@ -5385,6 +5385,7 @@ extern bool real_minus_onep (const_tree);
> > > extern void init_ttree (void);
> > > extern void build_common_tree_nodes (bool);
> > > extern void build_common_builtin_nodes (void);
> > > +extern void tree_cc_finalize (void);
> > > extern tree build_nonstandard_integer_type (unsigned
> > > HOST_WIDE_INT, int);
> > > extern tree build_nonstandard_boolean_type (unsigned
> > > HOST_WIDE_INT);
> > > extern tree build_range_type (tree, tree, tree);
> >
> > Looks OK to me, but am not officially a maintainer of these parts.
> >
> > LGTM with those nits fixed - for next stage 1, or for trunk now if
> > the
> > release maintainers are OK with it.
> >
> > Thanks again for the patch, and sorry about the belated review.
> >
> > Dave
> >
> >
> >
>
^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2022-04-12 21:39 UTC | newest]
Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-01-17 22:18 [PATCH] libgccjit: Add support for bitcasts [PR104071] Antoni Boucher
2022-01-18 0:30 ` Antoni Boucher
2022-01-18 23:06 ` David Malcolm
2022-01-21 23:41 ` Antoni Boucher
2022-04-08 19:22 ` David Malcolm
2022-04-09 18:05 ` Antoni Boucher
2022-04-12 21:39 ` David Malcolm
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).