From: Antoni Boucher <bouanto@zoho.com>
To: David Malcolm <dmalcolm@redhat.com>,
gcc-patches@gcc.gnu.org, jit@gcc.gnu.org
Subject: Re: [PATCH] libgccjit: Add support for bitcasts [PR104071]
Date: Sat, 09 Apr 2022 14:05:56 -0400 [thread overview]
Message-ID: <0df71b1c19605b54908f71795c7a008b2a22c559.camel@zoho.com> (raw)
In-Reply-To: <ac8760b11de7eb23f91ba092933becb481ed8fa9.camel@redhat.com>
[-- 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
next prev parent reply other threads:[~2022-04-09 18:06 UTC|newest]
Thread overview: 7+ messages / expand[flat|nested] mbox.gz Atom feed top
2022-01-17 22:18 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 [this message]
2022-04-12 21:39 ` David Malcolm
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=0df71b1c19605b54908f71795c7a008b2a22c559.camel@zoho.com \
--to=bouanto@zoho.com \
--cc=dmalcolm@redhat.com \
--cc=gcc-patches@gcc.gnu.org \
--cc=jit@gcc.gnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).