public inbox for jit@gcc.gnu.org
 help / color / mirror / Atom feed
* [PATCH] libgccjit: add some reflection functions in the jit C api
@ 2020-09-02  1:01 Antoni Boucher
  2020-10-02 20:17 ` David Malcolm
  0 siblings, 1 reply; 35+ messages in thread
From: Antoni Boucher @ 2020-09-02  1:01 UTC (permalink / raw)
  To: gcc-patches, jit

[-- Attachment #1: Type: text/plain, Size: 224 bytes --]

Hello.
This WIP patch implements new reflection functions in the C API as 
mentioned in bug 96889.
I'm looking forward for feedbacks on this patch.
It's WIP because I'll probably add a few more reflection functions.
Thanks.

[-- Attachment #2: 0001-This-patch-add-some-reflection-functions-in-the-jit-.patch --]
[-- Type: text/plain, Size: 7637 bytes --]

From 23ab738c0d9202f6798a38fb4aa15edfcc67d11c Mon Sep 17 00:00:00 2001
From: Antoni Boucher <bouanto@zoho.com>
Date: Sat, 1 Aug 2020 17:52:17 -0400
Subject: [PATCH] This patch add some reflection functions in the jit C api.

2020-09-1  Antoni Boucher  <bouanto@zoho.com>

    gcc/jit/
            PR target/96889
            * docs/topics/compatibility.rst (LIBGCCJIT_ABI_14): New ABI tag.
            * docs/topics/functions.rst: Add documentation for the
            functions gcc_jit_function_get_return_type and
            gcc_jit_function_get_param_count
            * libgccjit.c (gcc_jit_function_get_param_count and
            gcc_jit_function_get_return_type): New functions.
            * libgccjit.h
            * libgccjit.map (LIBGCCJIT_ABI_14): New ABI tag.

    gcc/testsuite/
            PR target/96889
            * jit.dg/all-non-failing-tests.h: Add test-reflection.c.
            * jit.dg/test-reflection.c: New test.
---
 gcc/jit/docs/topics/compatibility.rst        | 11 ++++++++
 gcc/jit/docs/topics/functions.rst            | 10 +++++++
 gcc/jit/libgccjit.c                          | 28 ++++++++++++++++++++
 gcc/jit/libgccjit.h                          | 24 +++++++++++++++++
 gcc/jit/libgccjit.map                        |  8 +++++-
 gcc/testsuite/jit.dg/all-non-failing-tests.h | 10 +++++++
 gcc/testsuite/jit.dg/test-reflection.c       | 27 +++++++++++++++++++
 7 files changed, 117 insertions(+), 1 deletion(-)
 create mode 100644 gcc/testsuite/jit.dg/test-reflection.c

diff --git a/gcc/jit/docs/topics/compatibility.rst b/gcc/jit/docs/topics/compatibility.rst
index bb3387fa583..7e786194ded 100644
--- a/gcc/jit/docs/topics/compatibility.rst
+++ b/gcc/jit/docs/topics/compatibility.rst
@@ -219,3 +219,14 @@ entrypoints:
   * :func:`gcc_jit_version_minor`
 
   * :func:`gcc_jit_version_patchlevel`
+
+.. _LIBGCCJIT_ABI_14:
+
+``LIBGCCJIT_ABI_14``
+--------------------
+``LIBGCCJIT_ABI_14`` covers the addition of reflection functions via API
+entrypoints:
+
+  * :func:`gcc_jit_function_get_return_type`
+
+  * :func:`gcc_jit_function_get_param_count`
diff --git a/gcc/jit/docs/topics/functions.rst b/gcc/jit/docs/topics/functions.rst
index eb40d64010e..9819c28cda2 100644
--- a/gcc/jit/docs/topics/functions.rst
+++ b/gcc/jit/docs/topics/functions.rst
@@ -171,6 +171,16 @@ Functions
    underlying string, so it is valid to pass in a pointer to an on-stack
    buffer.
 
+.. function::  size_t \
+               gcc_jit_function_get_param_count (gcc_jit_function *func)
+
+   Get the number of parameters of the function.
+
+.. function::  gcc_jit_type \*
+               gcc_jit_function_get_return_type (gcc_jit_function *func)
+
+   Get the return type of the function.
+
 Blocks
 ------
 .. type:: gcc_jit_block
diff --git a/gcc/jit/libgccjit.c b/gcc/jit/libgccjit.c
index 50130fbbe00..e3f8dd33665 100644
--- a/gcc/jit/libgccjit.c
+++ b/gcc/jit/libgccjit.c
@@ -1012,6 +1012,34 @@ gcc_jit_function_get_param (gcc_jit_function *func, int index)
   return static_cast <gcc_jit_param *> (func->get_param (index));
 }
 
+/* Public entrypoint.  See description in libgccjit.h.
+
+   After error-checking, the real work is done by the
+   gcc::jit::recording::function::get_params method, in
+   jit-recording.h.
+  */
+
+size_t
+gcc_jit_function_get_param_count (gcc_jit_function *func)
+{
+  RETURN_NULL_IF_FAIL (func, NULL, NULL, "NULL function");
+  gcc::jit::recording::context *ctxt = func->m_ctxt;
+  JIT_LOG_FUNC (ctxt->get_logger ());
+  return func->get_params ().length ();
+}
+
+/* Public entrypoint.  See description in libgccjit.h.
+
+   After error-checking, the real work is done by the
+   gcc::jit::recording::function::get_return_type method, in
+   jit-recording.h.  */
+
+gcc_jit_type *
+gcc_jit_function_get_return_type (gcc_jit_function *func)
+{
+    return (gcc_jit_type *)func->get_return_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 1c5a12e9c01..6999ce25ca2 100644
--- a/gcc/jit/libgccjit.h
+++ b/gcc/jit/libgccjit.h
@@ -740,6 +740,14 @@ gcc_jit_function_as_object (gcc_jit_function *func);
 extern gcc_jit_param *
 gcc_jit_function_get_param (gcc_jit_function *func, int index);
 
+/* Get the number of params of a function.  */
+extern size_t
+gcc_jit_function_get_param_count (gcc_jit_function *func);
+
+/* Get the return type of a function.  */
+extern gcc_jit_type *
+gcc_jit_function_get_return_type (gcc_jit_function *func);
+
 /* Emit the function in graphviz format.  */
 extern void
 gcc_jit_function_dump_to_dot (gcc_jit_function *func,
@@ -1503,6 +1511,22 @@ gcc_jit_version_minor (void);
 extern int
 gcc_jit_version_patchlevel (void);
 
+#define LIBGCCJIT_HAVE_gcc_jit_function_reflection
+
+/* Reflection functions to get the number of parameters and return types of
+   a function from the C API.
+
+   "vec_type" should be a vector type, created using gcc_jit_type_get_vector.
+
+   This API entrypoint was added in LIBGCCJIT_ABI_14; you can test for its
+   presence using
+     #ifdef LIBGCCJIT_HAVE_gcc_jit_function_reflection
+*/
+extern gcc_jit_type *
+gcc_jit_function_get_return_type (gcc_jit_function *func);
+extern size_t
+gcc_jit_function_get_param_count (gcc_jit_function *func);
+
 #ifdef __cplusplus
 }
 #endif /* __cplusplus */
diff --git a/gcc/jit/libgccjit.map b/gcc/jit/libgccjit.map
index 6137dd4b4b0..b28f81a7a32 100644
--- a/gcc/jit/libgccjit.map
+++ b/gcc/jit/libgccjit.map
@@ -186,4 +186,10 @@ LIBGCCJIT_ABI_13 {
     gcc_jit_version_major;
     gcc_jit_version_minor;
     gcc_jit_version_patchlevel;
-} LIBGCCJIT_ABI_12;
\ No newline at end of file
+} LIBGCCJIT_ABI_12;
+
+LIBGCCJIT_ABI_14 {
+  global:
+    gcc_jit_function_get_return_type;
+    gcc_jit_function_get_param_count;
+} LIBGCCJIT_ABI_13;
diff --git a/gcc/testsuite/jit.dg/all-non-failing-tests.h b/gcc/testsuite/jit.dg/all-non-failing-tests.h
index 632ab8cfb2e..c59af802f16 100644
--- a/gcc/testsuite/jit.dg/all-non-failing-tests.h
+++ b/gcc/testsuite/jit.dg/all-non-failing-tests.h
@@ -251,6 +251,13 @@
 #undef create_code
 #undef verify_code
 
+/* test-reflection.c */
+#define create_code create_code_reflection
+#define verify_code verify_code_reflection
+#include "test-reflection.c"
+#undef create_code
+#undef verify_code
+
 /* test-string-literal.c */
 #define create_code create_code_string_literal
 #define verify_code verify_code_string_literal
@@ -417,6 +424,9 @@ const struct testcase testcases[] = {
   {"reading_struct ",
    create_code_reading_struct ,
    verify_code_reading_struct },
+  {"reflection",
+   create_code_reflection ,
+   verify_code_reflection },
   {"string_literal",
    create_code_string_literal,
    verify_code_string_literal},
diff --git a/gcc/testsuite/jit.dg/test-reflection.c b/gcc/testsuite/jit.dg/test-reflection.c
new file mode 100644
index 00000000000..b39e9abab33
--- /dev/null
+++ b/gcc/testsuite/jit.dg/test-reflection.c
@@ -0,0 +1,27 @@
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "libgccjit.h"
+
+#include "harness.h"
+
+void
+create_code (gcc_jit_context *ctxt, void *user_data)
+{
+  /* Do nothing.  */
+}
+
+void
+verify_code (gcc_jit_context *ctxt, gcc_jit_result *result)
+{
+  /* Get the built-in functions.  */
+  gcc_jit_function *builtin_sin =
+    gcc_jit_context_get_builtin_function (ctxt, "sin");
+
+  CHECK_VALUE (gcc_jit_function_get_param_count(builtin_sin), 1);
+
+  gcc_jit_type *double_type =
+    gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_DOUBLE);
+  CHECK_VALUE (gcc_jit_function_get_return_type(builtin_sin), double_type);
+}
+
-- 
2.28.0


^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re: [PATCH] libgccjit: add some reflection functions in the jit C api
  2020-09-02  1:01 [PATCH] libgccjit: add some reflection functions in the jit C api Antoni Boucher
@ 2020-10-02 20:17 ` David Malcolm
  2020-10-02 20:24   ` David Malcolm
  0 siblings, 1 reply; 35+ messages in thread
From: David Malcolm @ 2020-10-02 20:17 UTC (permalink / raw)
  To: Antoni Boucher, gcc-patches, jit

On Tue, 2020-09-01 at 21:01 -0400, Antoni Boucher via Jit wrote:
> Hello.
> This WIP patch implements new reflection functions in the C API as 
> mentioned in bug 96889.
> I'm looking forward for feedbacks on this patch.
> It's WIP because I'll probably add a few more reflection functions.
> Thanks.

Sorry about the belated review, looks like I missed this one.

At a high level, it seems reasonable.

Do you have a copyright assignment in place for GCC contributions?
See https://gcc.gnu.org/contribute.html

[...]
 
> diff --git a/gcc/jit/docs/topics/compatibility.rst b/gcc/jit/docs/topics/compatibility.rst
> index bb3387fa583..7e786194ded 100644
> --- a/gcc/jit/docs/topics/compatibility.rst
> +++ b/gcc/jit/docs/topics/compatibility.rst
> @@ -219,3 +219,14 @@ entrypoints:
>    * :func:`gcc_jit_version_minor`
>  
>    * :func:`gcc_jit_version_patchlevel`
> +
> +.. _LIBGCCJIT_ABI_14:
> +
> +``LIBGCCJIT_ABI_14``
> +--------------------
> +``LIBGCCJIT_ABI_14`` covers the addition of reflection functions via API
> +entrypoints:
> +
> +  * :func:`gcc_jit_function_get_return_type`
> +
> +  * :func:`gcc_jit_function_get_param_count`

This will now need bumping to 15; 14 covers the addition of
gcc_jit_global_set_initializer.

[...]

> +/* Public entrypoint.  See description in libgccjit.h.
> +
> +   After error-checking, the real work is done by the
> +   gcc::jit::recording::function::get_return_type method, in
> +   jit-recording.h.  */
> +
> +gcc_jit_type *
> +gcc_jit_function_get_return_type (gcc_jit_function *func)
> +{

This one is missing a:
  RETURN_NULL_IF_FAIL (func, NULL, NULL, "NULL function");


> +    return (gcc_jit_type *)func->get_return_type ();
> +}

[...]

> diff --git a/gcc/jit/libgccjit.h b/gcc/jit/libgccjit.h
> index 1c5a12e9c01..6999ce25ca2 100644
> --- a/gcc/jit/libgccjit.h
> +++ b/gcc/jit/libgccjit.h

[...]

> @@ -1503,6 +1511,22 @@ gcc_jit_version_minor (void);
>  extern int
>  gcc_jit_version_patchlevel (void);
>  
> +#define LIBGCCJIT_HAVE_gcc_jit_function_reflection
> +
> +/* Reflection functions to get the number of parameters and return types of
> +   a function from the C API.

"return type", is better grammar, I think, given that "function" is singular.

> +
> +   "vec_type" should be a vector type, created using gcc_jit_type_get_vector.

This line about "vec_type" seems to be a leftover from a copy&paste.


> +   This API entrypoint was added in LIBGCCJIT_ABI_14; you can test for its
> +   presence using
> +     #ifdef LIBGCCJIT_HAVE_gcc_jit_function_reflection

Version number will need bumping, as mentioned above.

[...]

> diff --git a/gcc/jit/libgccjit.map b/gcc/jit/libgccjit.map
> index 6137dd4b4b0..b28f81a7a32 100644
> --- a/gcc/jit/libgccjit.map
> +++ b/gcc/jit/libgccjit.map
> @@ -186,4 +186,10 @@ LIBGCCJIT_ABI_13 {
>      gcc_jit_version_major;
>      gcc_jit_version_minor;
>      gcc_jit_version_patchlevel;
> -} LIBGCCJIT_ABI_12;
> \ No newline at end of file
> +} LIBGCCJIT_ABI_12;
> +
> +LIBGCCJIT_ABI_14 {
> +  global:
> +    gcc_jit_function_get_return_type;
> +    gcc_jit_function_get_param_count;
> +} LIBGCCJIT_ABI_13;

Likewise.

[...]

Otherwise looks good to me.

Bonus points for adding C++ bindings (and docs for them), but I don't
know of anyone using the C++ bindings.

Dave


^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re: [PATCH] libgccjit: add some reflection functions in the jit C api
  2020-10-02 20:17 ` David Malcolm
@ 2020-10-02 20:24   ` David Malcolm
  2020-10-02 22:39     ` [PATCH] libgccjit: add some reflection functions in the jit C api [PR96889] Antoni Boucher
                       ` (2 more replies)
  0 siblings, 3 replies; 35+ messages in thread
From: David Malcolm @ 2020-10-02 20:24 UTC (permalink / raw)
  To: Antoni Boucher, gcc-patches, jit

On Fri, 2020-10-02 at 16:17 -0400, David Malcolm wrote:
> On Tue, 2020-09-01 at 21:01 -0400, Antoni Boucher via Jit wrote:
> > Hello.
> > This WIP patch implements new reflection functions in the C API as 
> > mentioned in bug 96889.
> > I'm looking forward for feedbacks on this patch.
> > It's WIP because I'll probably add a few more reflection functions.
> > Thanks.
> 
> Sorry about the belated review, looks like I missed this one.
> 
> At a high level, it seems reasonable.
> 
> Do you have a copyright assignment in place for GCC contributions?
> See https://gcc.gnu.org/contribute.html
> 
> [...]

diff --git a/gcc/jit/docs/topics/compatibility.rst
> > b/gcc/jit/docs/topics/compatibility.rst
> > index bb3387fa583..7e786194ded 100644
> > --- a/gcc/jit/docs/topics/compatibility.rst
> > +++ b/gcc/jit/docs/topics/compatibility.rst
> > @@ -219,3 +219,14 @@ entrypoints:
> >    * :func:`gcc_jit_version_minor`
> >  
> >    * :func:`gcc_jit_version_patchlevel`
> > +
> > +.. _LIBGCCJIT_ABI_14:
> > +
> > +``LIBGCCJIT_ABI_14``
> > +--------------------
> > +``LIBGCCJIT_ABI_14`` covers the addition of reflection functions
> > via API
> > +entrypoints:
> > +
> > +  * :func:`gcc_jit_function_get_return_type`
> > +
> > +  * :func:`gcc_jit_function_get_param_count`
> 
> This will now need bumping to 15; 14 covers the addition of
> gcc_jit_global_set_initializer.
> 
> [...]
> 
> > +/* Public entrypoint.  See description in libgccjit.h.
> > +
> > +   After error-checking, the real work is done by the
> > +   gcc::jit::recording::function::get_return_type method, in
> > +   jit-recording.h.  */
> > +
> > +gcc_jit_type *
> > +gcc_jit_function_get_return_type (gcc_jit_function *func)
> > +{
> 
> This one is missing a:
>   RETURN_NULL_IF_FAIL (func, NULL, NULL, "NULL function");
> 
> 
> > +    return (gcc_jit_type *)func->get_return_type ();
> > +}
> 
> [...]
> 
> > diff --git a/gcc/jit/libgccjit.h b/gcc/jit/libgccjit.h
> > index 1c5a12e9c01..6999ce25ca2 100644
> > --- a/gcc/jit/libgccjit.h
> > +++ b/gcc/jit/libgccjit.h
> 
> [...]
> 
> > @@ -1503,6 +1511,22 @@ gcc_jit_version_minor (void);
> >  extern int
> >  gcc_jit_version_patchlevel (void);
> >  
> > +#define LIBGCCJIT_HAVE_gcc_jit_function_reflection
> > +
> > +/* Reflection functions to get the number of parameters and return
> > types of
> > +   a function from the C API.
> 
> "return type", is better grammar, I think, given that "function" is
> singular.
> 
> > +
> > +   "vec_type" should be a vector type, created using
> > gcc_jit_type_get_vector.
> 
> This line about "vec_type" seems to be a leftover from a copy&paste.
> 
> 
> > +   This API entrypoint was added in LIBGCCJIT_ABI_14; you can test
> > for its
> > +   presence using
> > +     #ifdef LIBGCCJIT_HAVE_gcc_jit_function_reflection
> 
> Version number will need bumping, as mentioned above.
> 
> [...]
> 
> > diff --git a/gcc/jit/libgccjit.map b/gcc/jit/libgccjit.map
> > index 6137dd4b4b0..b28f81a7a32 100644
> > --- a/gcc/jit/libgccjit.map
> > +++ b/gcc/jit/libgccjit.map
> > @@ -186,4 +186,10 @@ LIBGCCJIT_ABI_13 {
> >      gcc_jit_version_major;
> >      gcc_jit_version_minor;
> >      gcc_jit_version_patchlevel;
> > -} LIBGCCJIT_ABI_12;
> > \ No newline at end of file
> > +} LIBGCCJIT_ABI_12;
> > +
> > +LIBGCCJIT_ABI_14 {
> > +  global:
> > +    gcc_jit_function_get_return_type;
> > +    gcc_jit_function_get_param_count;
> > +} LIBGCCJIT_ABI_13;
> 
> Likewise.
> 
> [...]
> 
> Otherwise looks good to me.
> 
> Bonus points for adding C++ bindings (and docs for them), but I don't
> know of anyone using the C++ bindings.


Also, please add "PR jit/96889" to the ChangeLog entries, and [PR96889]
to the subject line.

Dave


^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re: [PATCH] libgccjit: add some reflection functions in the jit C api [PR96889]
  2020-10-02 20:24   ` David Malcolm
@ 2020-10-02 22:39     ` Antoni Boucher
  2020-10-03 18:14     ` [PATCH] libgccjit: add some reflection functions in the jit C api [WIP] Antoni Boucher
  2020-10-15 16:02     ` [PATCH] libgccjit: add some reflection functions in the jit C api Antoni Boucher
  2 siblings, 0 replies; 35+ messages in thread
From: Antoni Boucher @ 2020-10-02 22:39 UTC (permalink / raw)
  To: David Malcolm; +Cc: gcc-patches, jit

[-- Attachment #1: Type: text/plain, Size: 3967 bytes --]

Hi.
Thanks for the review.
I attached the updated patch file.
I don't have a copyright assignment, but I'll look at that.

On Fri, Oct 02, 2020 at 04:24:26PM -0400, David Malcolm wrote:
>On Fri, 2020-10-02 at 16:17 -0400, David Malcolm wrote:
>> On Tue, 2020-09-01 at 21:01 -0400, Antoni Boucher via Jit wrote:
>> > Hello.
>> > This WIP patch implements new reflection functions in the C API as
>> > mentioned in bug 96889.
>> > I'm looking forward for feedbacks on this patch.
>> > It's WIP because I'll probably add a few more reflection functions.
>> > Thanks.
>>
>> Sorry about the belated review, looks like I missed this one.
>>
>> At a high level, it seems reasonable.
>>
>> Do you have a copyright assignment in place for GCC contributions?
>> See https://gcc.gnu.org/contribute.html
>>
>> [...]
>
>diff --git a/gcc/jit/docs/topics/compatibility.rst
>> > b/gcc/jit/docs/topics/compatibility.rst
>> > index bb3387fa583..7e786194ded 100644
>> > --- a/gcc/jit/docs/topics/compatibility.rst
>> > +++ b/gcc/jit/docs/topics/compatibility.rst
>> > @@ -219,3 +219,14 @@ entrypoints:
>> >    * :func:`gcc_jit_version_minor`
>> >
>> >    * :func:`gcc_jit_version_patchlevel`
>> > +
>> > +.. _LIBGCCJIT_ABI_14:
>> > +
>> > +``LIBGCCJIT_ABI_14``
>> > +--------------------
>> > +``LIBGCCJIT_ABI_14`` covers the addition of reflection functions
>> > via API
>> > +entrypoints:
>> > +
>> > +  * :func:`gcc_jit_function_get_return_type`
>> > +
>> > +  * :func:`gcc_jit_function_get_param_count`
>>
>> This will now need bumping to 15; 14 covers the addition of
>> gcc_jit_global_set_initializer.
>>
>> [...]
>>
>> > +/* Public entrypoint.  See description in libgccjit.h.
>> > +
>> > +   After error-checking, the real work is done by the
>> > +   gcc::jit::recording::function::get_return_type method, in
>> > +   jit-recording.h.  */
>> > +
>> > +gcc_jit_type *
>> > +gcc_jit_function_get_return_type (gcc_jit_function *func)
>> > +{
>>
>> This one is missing a:
>>   RETURN_NULL_IF_FAIL (func, NULL, NULL, "NULL function");
>>
>>
>> > +    return (gcc_jit_type *)func->get_return_type ();
>> > +}
>>
>> [...]
>>
>> > diff --git a/gcc/jit/libgccjit.h b/gcc/jit/libgccjit.h
>> > index 1c5a12e9c01..6999ce25ca2 100644
>> > --- a/gcc/jit/libgccjit.h
>> > +++ b/gcc/jit/libgccjit.h
>>
>> [...]
>>
>> > @@ -1503,6 +1511,22 @@ gcc_jit_version_minor (void);
>> >  extern int
>> >  gcc_jit_version_patchlevel (void);
>> >
>> > +#define LIBGCCJIT_HAVE_gcc_jit_function_reflection
>> > +
>> > +/* Reflection functions to get the number of parameters and return
>> > types of
>> > +   a function from the C API.
>>
>> "return type", is better grammar, I think, given that "function" is
>> singular.
>>
>> > +
>> > +   "vec_type" should be a vector type, created using
>> > gcc_jit_type_get_vector.
>>
>> This line about "vec_type" seems to be a leftover from a copy&paste.
>>
>>
>> > +   This API entrypoint was added in LIBGCCJIT_ABI_14; you can test
>> > for its
>> > +   presence using
>> > +     #ifdef LIBGCCJIT_HAVE_gcc_jit_function_reflection
>>
>> Version number will need bumping, as mentioned above.
>>
>> [...]
>>
>> > diff --git a/gcc/jit/libgccjit.map b/gcc/jit/libgccjit.map
>> > index 6137dd4b4b0..b28f81a7a32 100644
>> > --- a/gcc/jit/libgccjit.map
>> > +++ b/gcc/jit/libgccjit.map
>> > @@ -186,4 +186,10 @@ LIBGCCJIT_ABI_13 {
>> >      gcc_jit_version_major;
>> >      gcc_jit_version_minor;
>> >      gcc_jit_version_patchlevel;
>> > -} LIBGCCJIT_ABI_12;
>> > \ No newline at end of file
>> > +} LIBGCCJIT_ABI_12;
>> > +
>> > +LIBGCCJIT_ABI_14 {
>> > +  global:
>> > +    gcc_jit_function_get_return_type;
>> > +    gcc_jit_function_get_param_count;
>> > +} LIBGCCJIT_ABI_13;
>>
>> Likewise.
>>
>> [...]
>>
>> Otherwise looks good to me.
>>
>> Bonus points for adding C++ bindings (and docs for them), but I don't
>> know of anyone using the C++ bindings.
>
>
>Also, please add "PR jit/96889" to the ChangeLog entries, and [PR96889]
>to the subject line.
>
>Dave
>

[-- Attachment #2: 0001-This-patch-add-some-reflection-functions-in-the-jit-.patch --]
[-- Type: text/plain, Size: 7546 bytes --]

From ef3b7d15622cc50dc4cae62fb7c31aeacc0f1ed9 Mon Sep 17 00:00:00 2001
From: Antoni Boucher <bouanto@zoho.com>
Date: Sat, 1 Aug 2020 17:52:17 -0400
Subject: [PATCH] This patch add some reflection functions in the jit C api
 [PR96889]

2020-09-1  Antoni Boucher  <bouanto@zoho.com>

    gcc/jit/
            PR target/96889
            * docs/topics/compatibility.rst (LIBGCCJIT_ABI_14): New ABI tag.
            * docs/topics/functions.rst: Add documentation for the
            functions gcc_jit_function_get_return_type and
            gcc_jit_function_get_param_count
            * libgccjit.c (gcc_jit_function_get_param_count and
            gcc_jit_function_get_return_type): New functions.
            * libgccjit.h
            * libgccjit.map (LIBGCCJIT_ABI_14): New ABI tag.

    gcc/testsuite/
            PR target/96889
            * jit.dg/all-non-failing-tests.h: Add test-reflection.c.
            * jit.dg/test-reflection.c: New test.
---
 gcc/jit/docs/topics/compatibility.rst        | 11 ++++++++
 gcc/jit/docs/topics/functions.rst            | 10 +++++++
 gcc/jit/libgccjit.c                          | 29 ++++++++++++++++++++
 gcc/jit/libgccjit.h                          | 22 +++++++++++++++
 gcc/jit/libgccjit.map                        |  6 ++++
 gcc/testsuite/jit.dg/all-non-failing-tests.h | 10 +++++++
 gcc/testsuite/jit.dg/test-reflection.c       | 27 ++++++++++++++++++
 7 files changed, 115 insertions(+)
 create mode 100644 gcc/testsuite/jit.dg/test-reflection.c

diff --git a/gcc/jit/docs/topics/compatibility.rst b/gcc/jit/docs/topics/compatibility.rst
index 6bfa101ed71..eb6acf91c44 100644
--- a/gcc/jit/docs/topics/compatibility.rst
+++ b/gcc/jit/docs/topics/compatibility.rst
@@ -226,3 +226,14 @@ entrypoints:
 --------------------
 ``LIBGCCJIT_ABI_14`` covers the addition of
 :func:`gcc_jit_global_set_initializer`
+
+.. _LIBGCCJIT_ABI_15:
+
+``LIBGCCJIT_ABI_15``
+--------------------
+``LIBGCCJIT_ABI_15`` covers the addition of reflection functions via API
+entrypoints:
+
+  * :func:`gcc_jit_function_get_return_type`
+
+  * :func:`gcc_jit_function_get_param_count`
diff --git a/gcc/jit/docs/topics/functions.rst b/gcc/jit/docs/topics/functions.rst
index eb40d64010e..9819c28cda2 100644
--- a/gcc/jit/docs/topics/functions.rst
+++ b/gcc/jit/docs/topics/functions.rst
@@ -171,6 +171,16 @@ Functions
    underlying string, so it is valid to pass in a pointer to an on-stack
    buffer.
 
+.. function::  size_t \
+               gcc_jit_function_get_param_count (gcc_jit_function *func)
+
+   Get the number of parameters of the function.
+
+.. function::  gcc_jit_type \*
+               gcc_jit_function_get_return_type (gcc_jit_function *func)
+
+   Get the return type of the function.
+
 Blocks
 ------
 .. type:: gcc_jit_block
diff --git a/gcc/jit/libgccjit.c b/gcc/jit/libgccjit.c
index a00aefc7108..352e1b84f3c 100644
--- a/gcc/jit/libgccjit.c
+++ b/gcc/jit/libgccjit.c
@@ -1012,6 +1012,35 @@ gcc_jit_function_get_param (gcc_jit_function *func, int index)
   return static_cast <gcc_jit_param *> (func->get_param (index));
 }
 
+/* Public entrypoint.  See description in libgccjit.h.
+
+   After error-checking, the real work is done by the
+   gcc::jit::recording::function::get_params method, in
+   jit-recording.h.
+  */
+
+size_t
+gcc_jit_function_get_param_count (gcc_jit_function *func)
+{
+  RETURN_NULL_IF_FAIL (func, NULL, NULL, "NULL function");
+  gcc::jit::recording::context *ctxt = func->m_ctxt;
+  JIT_LOG_FUNC (ctxt->get_logger ());
+  return func->get_params ().length ();
+}
+
+/* Public entrypoint.  See description in libgccjit.h.
+
+   After error-checking, the real work is done by the
+   gcc::jit::recording::function::get_return_type method, in
+   jit-recording.h.  */
+
+gcc_jit_type *
+gcc_jit_function_get_return_type (gcc_jit_function *func)
+{
+    RETURN_NULL_IF_FAIL (func, NULL, NULL, "NULL function");
+    return (gcc_jit_type *)func->get_return_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 7134841bb07..38c04a2356f 100644
--- a/gcc/jit/libgccjit.h
+++ b/gcc/jit/libgccjit.h
@@ -740,6 +740,14 @@ gcc_jit_function_as_object (gcc_jit_function *func);
 extern gcc_jit_param *
 gcc_jit_function_get_param (gcc_jit_function *func, int index);
 
+/* Get the number of params of a function.  */
+extern size_t
+gcc_jit_function_get_param_count (gcc_jit_function *func);
+
+/* Get the return type of a function.  */
+extern gcc_jit_type *
+gcc_jit_function_get_return_type (gcc_jit_function *func);
+
 /* Emit the function in graphviz format.  */
 extern void
 gcc_jit_function_dump_to_dot (gcc_jit_function *func,
@@ -1518,6 +1526,20 @@ gcc_jit_version_minor (void);
 extern int
 gcc_jit_version_patchlevel (void);
 
+#define LIBGCCJIT_HAVE_gcc_jit_function_reflection
+
+/* Reflection functions to get the number of parameters and return type of
+   a function from the C API.
+
+   This API entrypoint was added in LIBGCCJIT_ABI_15; you can test for its
+   presence using
+     #ifdef LIBGCCJIT_HAVE_gcc_jit_function_reflection
+*/
+extern gcc_jit_type *
+gcc_jit_function_get_return_type (gcc_jit_function *func);
+extern size_t
+gcc_jit_function_get_param_count (gcc_jit_function *func);
+
 #ifdef __cplusplus
 }
 #endif /* __cplusplus */
diff --git a/gcc/jit/libgccjit.map b/gcc/jit/libgccjit.map
index a6e67e781a4..ce12fae626f 100644
--- a/gcc/jit/libgccjit.map
+++ b/gcc/jit/libgccjit.map
@@ -192,3 +192,9 @@ LIBGCCJIT_ABI_14 {
   global:
     gcc_jit_global_set_initializer;
 } LIBGCCJIT_ABI_13;
+
+LIBGCCJIT_ABI_15 {
+  global:
+    gcc_jit_function_get_return_type;
+    gcc_jit_function_get_param_count;
+} LIBGCCJIT_ABI_14;
diff --git a/gcc/testsuite/jit.dg/all-non-failing-tests.h b/gcc/testsuite/jit.dg/all-non-failing-tests.h
index 4202eb7798b..a269144d2df 100644
--- a/gcc/testsuite/jit.dg/all-non-failing-tests.h
+++ b/gcc/testsuite/jit.dg/all-non-failing-tests.h
@@ -258,6 +258,13 @@
 #undef create_code
 #undef verify_code
 
+/* test-reflection.c */
+#define create_code create_code_reflection
+#define verify_code verify_code_reflection
+#include "test-reflection.c"
+#undef create_code
+#undef verify_code
+
 /* test-string-literal.c */
 #define create_code create_code_string_literal
 #define verify_code verify_code_string_literal
@@ -424,6 +431,9 @@ const struct testcase testcases[] = {
   {"reading_struct ",
    create_code_reading_struct ,
    verify_code_reading_struct },
+  {"reflection",
+   create_code_reflection ,
+   verify_code_reflection },
   {"string_literal",
    create_code_string_literal,
    verify_code_string_literal},
diff --git a/gcc/testsuite/jit.dg/test-reflection.c b/gcc/testsuite/jit.dg/test-reflection.c
new file mode 100644
index 00000000000..b39e9abab33
--- /dev/null
+++ b/gcc/testsuite/jit.dg/test-reflection.c
@@ -0,0 +1,27 @@
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "libgccjit.h"
+
+#include "harness.h"
+
+void
+create_code (gcc_jit_context *ctxt, void *user_data)
+{
+  /* Do nothing.  */
+}
+
+void
+verify_code (gcc_jit_context *ctxt, gcc_jit_result *result)
+{
+  /* Get the built-in functions.  */
+  gcc_jit_function *builtin_sin =
+    gcc_jit_context_get_builtin_function (ctxt, "sin");
+
+  CHECK_VALUE (gcc_jit_function_get_param_count(builtin_sin), 1);
+
+  gcc_jit_type *double_type =
+    gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_DOUBLE);
+  CHECK_VALUE (gcc_jit_function_get_return_type(builtin_sin), double_type);
+}
+
-- 
2.28.0


^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re: [PATCH] libgccjit: add some reflection functions in the jit C api [WIP]
  2020-10-02 20:24   ` David Malcolm
  2020-10-02 22:39     ` [PATCH] libgccjit: add some reflection functions in the jit C api [PR96889] Antoni Boucher
@ 2020-10-03 18:14     ` Antoni Boucher
  2020-10-15 16:02     ` [PATCH] libgccjit: add some reflection functions in the jit C api Antoni Boucher
  2 siblings, 0 replies; 35+ messages in thread
From: Antoni Boucher @ 2020-10-03 18:14 UTC (permalink / raw)
  To: David Malcolm; +Cc: gcc-patches, jit

By the way, that seemed off to return NULL for the function returning a 
size_t to indicate an error. So I changed it to return -1 (and return 
type to ssize_t).  Is that the proper way to indicate an error?

I also wanted to mention that this patch is still a work-in-progress as 
I'm adding a few other functions.

On Fri, Oct 02, 2020 at 04:24:26PM -0400, David Malcolm wrote:
>On Fri, 2020-10-02 at 16:17 -0400, David Malcolm wrote:
>> On Tue, 2020-09-01 at 21:01 -0400, Antoni Boucher via Jit wrote:
>> > Hello.
>> > This WIP patch implements new reflection functions in the C API as
>> > mentioned in bug 96889.
>> > I'm looking forward for feedbacks on this patch.
>> > It's WIP because I'll probably add a few more reflection functions.
>> > Thanks.
>>
>> Sorry about the belated review, looks like I missed this one.
>>
>> At a high level, it seems reasonable.
>>
>> Do you have a copyright assignment in place for GCC contributions?
>> See https://gcc.gnu.org/contribute.html
>>
>> [...]
>
>diff --git a/gcc/jit/docs/topics/compatibility.rst
>> > b/gcc/jit/docs/topics/compatibility.rst
>> > index bb3387fa583..7e786194ded 100644
>> > --- a/gcc/jit/docs/topics/compatibility.rst
>> > +++ b/gcc/jit/docs/topics/compatibility.rst
>> > @@ -219,3 +219,14 @@ entrypoints:
>> >    * :func:`gcc_jit_version_minor`
>> >
>> >    * :func:`gcc_jit_version_patchlevel`
>> > +
>> > +.. _LIBGCCJIT_ABI_14:
>> > +
>> > +``LIBGCCJIT_ABI_14``
>> > +--------------------
>> > +``LIBGCCJIT_ABI_14`` covers the addition of reflection functions
>> > via API
>> > +entrypoints:
>> > +
>> > +  * :func:`gcc_jit_function_get_return_type`
>> > +
>> > +  * :func:`gcc_jit_function_get_param_count`
>>
>> This will now need bumping to 15; 14 covers the addition of
>> gcc_jit_global_set_initializer.
>>
>> [...]
>>
>> > +/* Public entrypoint.  See description in libgccjit.h.
>> > +
>> > +   After error-checking, the real work is done by the
>> > +   gcc::jit::recording::function::get_return_type method, in
>> > +   jit-recording.h.  */
>> > +
>> > +gcc_jit_type *
>> > +gcc_jit_function_get_return_type (gcc_jit_function *func)
>> > +{
>>
>> This one is missing a:
>>   RETURN_NULL_IF_FAIL (func, NULL, NULL, "NULL function");
>>
>>
>> > +    return (gcc_jit_type *)func->get_return_type ();
>> > +}
>>
>> [...]
>>
>> > diff --git a/gcc/jit/libgccjit.h b/gcc/jit/libgccjit.h
>> > index 1c5a12e9c01..6999ce25ca2 100644
>> > --- a/gcc/jit/libgccjit.h
>> > +++ b/gcc/jit/libgccjit.h
>>
>> [...]
>>
>> > @@ -1503,6 +1511,22 @@ gcc_jit_version_minor (void);
>> >  extern int
>> >  gcc_jit_version_patchlevel (void);
>> >
>> > +#define LIBGCCJIT_HAVE_gcc_jit_function_reflection
>> > +
>> > +/* Reflection functions to get the number of parameters and return
>> > types of
>> > +   a function from the C API.
>>
>> "return type", is better grammar, I think, given that "function" is
>> singular.
>>
>> > +
>> > +   "vec_type" should be a vector type, created using
>> > gcc_jit_type_get_vector.
>>
>> This line about "vec_type" seems to be a leftover from a copy&paste.
>>
>>
>> > +   This API entrypoint was added in LIBGCCJIT_ABI_14; you can test
>> > for its
>> > +   presence using
>> > +     #ifdef LIBGCCJIT_HAVE_gcc_jit_function_reflection
>>
>> Version number will need bumping, as mentioned above.
>>
>> [...]
>>
>> > diff --git a/gcc/jit/libgccjit.map b/gcc/jit/libgccjit.map
>> > index 6137dd4b4b0..b28f81a7a32 100644
>> > --- a/gcc/jit/libgccjit.map
>> > +++ b/gcc/jit/libgccjit.map
>> > @@ -186,4 +186,10 @@ LIBGCCJIT_ABI_13 {
>> >      gcc_jit_version_major;
>> >      gcc_jit_version_minor;
>> >      gcc_jit_version_patchlevel;
>> > -} LIBGCCJIT_ABI_12;
>> > \ No newline at end of file
>> > +} LIBGCCJIT_ABI_12;
>> > +
>> > +LIBGCCJIT_ABI_14 {
>> > +  global:
>> > +    gcc_jit_function_get_return_type;
>> > +    gcc_jit_function_get_param_count;
>> > +} LIBGCCJIT_ABI_13;
>>
>> Likewise.
>>
>> [...]
>>
>> Otherwise looks good to me.
>>
>> Bonus points for adding C++ bindings (and docs for them), but I don't
>> know of anyone using the C++ bindings.
>
>
>Also, please add "PR jit/96889" to the ChangeLog entries, and [PR96889]
>to the subject line.
>
>Dave
>

^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re: [PATCH] libgccjit: add some reflection functions in the jit C api
  2020-10-02 20:24   ` David Malcolm
  2020-10-02 22:39     ` [PATCH] libgccjit: add some reflection functions in the jit C api [PR96889] Antoni Boucher
  2020-10-03 18:14     ` [PATCH] libgccjit: add some reflection functions in the jit C api [WIP] Antoni Boucher
@ 2020-10-15 16:02     ` Antoni Boucher
  2020-10-15 16:23       ` Andrea Corallo
  2 siblings, 1 reply; 35+ messages in thread
From: Antoni Boucher @ 2020-10-15 16:02 UTC (permalink / raw)
  To: David Malcolm; +Cc: gcc-patches, jit

[-- Attachment #1: Type: text/plain, Size: 3992 bytes --]

Hi.
I added all the functions I need in this new patch.
Please tell me if that looks good and I'll add documentation for those 
functions.
Thanks.

On Fri, Oct 02, 2020 at 04:24:26PM -0400, David Malcolm wrote:
>On Fri, 2020-10-02 at 16:17 -0400, David Malcolm wrote:
>> On Tue, 2020-09-01 at 21:01 -0400, Antoni Boucher via Jit wrote:
>> > Hello.
>> > This WIP patch implements new reflection functions in the C API as
>> > mentioned in bug 96889.
>> > I'm looking forward for feedbacks on this patch.
>> > It's WIP because I'll probably add a few more reflection functions.
>> > Thanks.
>>
>> Sorry about the belated review, looks like I missed this one.
>>
>> At a high level, it seems reasonable.
>>
>> Do you have a copyright assignment in place for GCC contributions?
>> See https://gcc.gnu.org/contribute.html
>>
>> [...]
>
>diff --git a/gcc/jit/docs/topics/compatibility.rst
>> > b/gcc/jit/docs/topics/compatibility.rst
>> > index bb3387fa583..7e786194ded 100644
>> > --- a/gcc/jit/docs/topics/compatibility.rst
>> > +++ b/gcc/jit/docs/topics/compatibility.rst
>> > @@ -219,3 +219,14 @@ entrypoints:
>> >    * :func:`gcc_jit_version_minor`
>> >
>> >    * :func:`gcc_jit_version_patchlevel`
>> > +
>> > +.. _LIBGCCJIT_ABI_14:
>> > +
>> > +``LIBGCCJIT_ABI_14``
>> > +--------------------
>> > +``LIBGCCJIT_ABI_14`` covers the addition of reflection functions
>> > via API
>> > +entrypoints:
>> > +
>> > +  * :func:`gcc_jit_function_get_return_type`
>> > +
>> > +  * :func:`gcc_jit_function_get_param_count`
>>
>> This will now need bumping to 15; 14 covers the addition of
>> gcc_jit_global_set_initializer.
>>
>> [...]
>>
>> > +/* Public entrypoint.  See description in libgccjit.h.
>> > +
>> > +   After error-checking, the real work is done by the
>> > +   gcc::jit::recording::function::get_return_type method, in
>> > +   jit-recording.h.  */
>> > +
>> > +gcc_jit_type *
>> > +gcc_jit_function_get_return_type (gcc_jit_function *func)
>> > +{
>>
>> This one is missing a:
>>   RETURN_NULL_IF_FAIL (func, NULL, NULL, "NULL function");
>>
>>
>> > +    return (gcc_jit_type *)func->get_return_type ();
>> > +}
>>
>> [...]
>>
>> > diff --git a/gcc/jit/libgccjit.h b/gcc/jit/libgccjit.h
>> > index 1c5a12e9c01..6999ce25ca2 100644
>> > --- a/gcc/jit/libgccjit.h
>> > +++ b/gcc/jit/libgccjit.h
>>
>> [...]
>>
>> > @@ -1503,6 +1511,22 @@ gcc_jit_version_minor (void);
>> >  extern int
>> >  gcc_jit_version_patchlevel (void);
>> >
>> > +#define LIBGCCJIT_HAVE_gcc_jit_function_reflection
>> > +
>> > +/* Reflection functions to get the number of parameters and return
>> > types of
>> > +   a function from the C API.
>>
>> "return type", is better grammar, I think, given that "function" is
>> singular.
>>
>> > +
>> > +   "vec_type" should be a vector type, created using
>> > gcc_jit_type_get_vector.
>>
>> This line about "vec_type" seems to be a leftover from a copy&paste.
>>
>>
>> > +   This API entrypoint was added in LIBGCCJIT_ABI_14; you can test
>> > for its
>> > +   presence using
>> > +     #ifdef LIBGCCJIT_HAVE_gcc_jit_function_reflection
>>
>> Version number will need bumping, as mentioned above.
>>
>> [...]
>>
>> > diff --git a/gcc/jit/libgccjit.map b/gcc/jit/libgccjit.map
>> > index 6137dd4b4b0..b28f81a7a32 100644
>> > --- a/gcc/jit/libgccjit.map
>> > +++ b/gcc/jit/libgccjit.map
>> > @@ -186,4 +186,10 @@ LIBGCCJIT_ABI_13 {
>> >      gcc_jit_version_major;
>> >      gcc_jit_version_minor;
>> >      gcc_jit_version_patchlevel;
>> > -} LIBGCCJIT_ABI_12;
>> > \ No newline at end of file
>> > +} LIBGCCJIT_ABI_12;
>> > +
>> > +LIBGCCJIT_ABI_14 {
>> > +  global:
>> > +    gcc_jit_function_get_return_type;
>> > +    gcc_jit_function_get_param_count;
>> > +} LIBGCCJIT_ABI_13;
>>
>> Likewise.
>>
>> [...]
>>
>> Otherwise looks good to me.
>>
>> Bonus points for adding C++ bindings (and docs for them), but I don't
>> know of anyone using the C++ bindings.
>
>
>Also, please add "PR jit/96889" to the ChangeLog entries, and [PR96889]
>to the subject line.
>
>Dave
>

[-- Attachment #2: 0001-This-patch-add-some-reflection-functions-in-the-jit-.patch --]
[-- Type: text/plain, Size: 28095 bytes --]

From b0edc9eb8e8d3ba9e1c6a8d061a8627c0b0cf102 Mon Sep 17 00:00:00 2001
From: Antoni Boucher <bouanto@zoho.com>
Date: Sat, 1 Aug 2020 17:52:17 -0400
Subject: [PATCH] This patch add some reflection functions in the jit C api
 [PR96889]

2020-09-1  Antoni Boucher  <bouanto@zoho.com>

    gcc/jit/
            PR target/96889
            * docs/topics/compatibility.rst (LIBGCCJIT_ABI_14): New ABI tag.
            * docs/topics/functions.rst: Add documentation for the
            functions gcc_jit_function_get_return_type and
            gcc_jit_function_get_param_count
            * libgccjit.c: New functions:
              * gcc_jit_function_get_return_type;
              * gcc_jit_function_get_param_count;
              * gcc_jit_function_type_get_return_type;
              * gcc_jit_function_type_get_param_count;
              * gcc_jit_function_type_get_param_type;
              * gcc_jit_type_unqualified;
              * gcc_jit_type_is_array;
              * gcc_jit_type_is_bool;
              * gcc_jit_type_is_function_ptr_type;
              * gcc_jit_type_is_int;
              * gcc_jit_type_is_pointer;
              * gcc_jit_type_is_vector;
              * gcc_jit_vector_type_get_element_type;
              * gcc_jit_vector_type_get_num_units;
              * gcc_jit_struct_get_field;
              * gcc_jit_type_is_struct;
              * gcc_jit_struct_get_field_count;
            * libgccjit.h
            * jit-recording.h: New functions (is_struct and is_vector)
            * libgccjit.map (LIBGCCJIT_ABI_14): New ABI tag.

    gcc/testsuite/
            PR target/96889
            * jit.dg/all-non-failing-tests.h: Add test-reflection.c.
            * jit.dg/test-reflection.c: New test.
---
 gcc/jit/docs/topics/compatibility.rst        |  41 +++
 gcc/jit/docs/topics/functions.rst            |  10 +
 gcc/jit/jit-recording.h                      |  16 ++
 gcc/jit/libgccjit.c                          | 254 +++++++++++++++++++
 gcc/jit/libgccjit.h                          | 117 +++++++++
 gcc/jit/libgccjit.map                        |  21 ++
 gcc/testsuite/jit.dg/all-non-failing-tests.h |  10 +
 gcc/testsuite/jit.dg/test-reflection.c       |  89 +++++++
 8 files changed, 558 insertions(+)
 create mode 100644 gcc/testsuite/jit.dg/test-reflection.c

diff --git a/gcc/jit/docs/topics/compatibility.rst b/gcc/jit/docs/topics/compatibility.rst
index 6bfa101ed71..16f24d20a75 100644
--- a/gcc/jit/docs/topics/compatibility.rst
+++ b/gcc/jit/docs/topics/compatibility.rst
@@ -226,3 +226,44 @@ entrypoints:
 --------------------
 ``LIBGCCJIT_ABI_14`` covers the addition of
 :func:`gcc_jit_global_set_initializer`
+
+.. _LIBGCCJIT_ABI_15:
+
+``LIBGCCJIT_ABI_15``
+--------------------
+``LIBGCCJIT_ABI_15`` covers the addition of reflection functions via API
+entrypoints:
+
+  * :func:`gcc_jit_function_get_return_type`
+
+  * :func:`gcc_jit_function_get_param_count`
+
+  * :func:`gcc_jit_type_is_array`
+
+  * :func:`gcc_jit_type_is_bool`
+
+  * :func:`gcc_jit_type_is_int`
+
+  * :func:`gcc_jit_type_is_pointer`
+
+  * :func:`gcc_jit_type_is_struct`
+
+  * :func:`gcc_jit_type_is_vector`
+
+  * :func:`gcc_jit_type_unqualified`
+
+  * :func:`gcc_jit_type_is_function_ptr_type`
+
+  * :func:`gcc_jit_function_type_get_return_type`
+
+  * :func:`gcc_jit_function_type_get_param_count`
+
+  * :func:`gcc_jit_function_type_get_param_type`
+
+  * :func:`gcc_jit_vector_type_get_num_units`
+
+  * :func:`gcc_jit_vector_type_get_element_type`
+
+  * :func:`gcc_jit_struct_get_field`
+
+  * :func:`gcc_jit_struct_get_field_count`
diff --git a/gcc/jit/docs/topics/functions.rst b/gcc/jit/docs/topics/functions.rst
index eb40d64010e..9819c28cda2 100644
--- a/gcc/jit/docs/topics/functions.rst
+++ b/gcc/jit/docs/topics/functions.rst
@@ -171,6 +171,16 @@ Functions
    underlying string, so it is valid to pass in a pointer to an on-stack
    buffer.
 
+.. function::  size_t \
+               gcc_jit_function_get_param_count (gcc_jit_function *func)
+
+   Get the number of parameters of the function.
+
+.. function::  gcc_jit_type \*
+               gcc_jit_function_get_return_type (gcc_jit_function *func)
+
+   Get the return type of the function.
+
 Blocks
 ------
 .. type:: gcc_jit_block
diff --git a/gcc/jit/jit-recording.h b/gcc/jit/jit-recording.h
index 30e37aff387..525b8bc921d 100644
--- a/gcc/jit/jit-recording.h
+++ b/gcc/jit/jit-recording.h
@@ -538,7 +538,9 @@ public:
   virtual bool is_bool () const = 0;
   virtual type *is_pointer () = 0;
   virtual type *is_array () = 0;
+  virtual struct_ *is_struct () { return NULL; }
   virtual bool is_void () const { return false; }
+  virtual vector_type *is_vector () { return NULL; }
   virtual bool has_known_size () const { return true; }
 
   bool is_numeric () const
@@ -595,6 +597,8 @@ public:
   bool is_bool () const FINAL OVERRIDE;
   type *is_pointer () FINAL OVERRIDE { return dereference (); }
   type *is_array () FINAL OVERRIDE { return NULL; }
+  vector_type *is_vector () FINAL OVERRIDE { return NULL; }
+  struct_ *is_struct () FINAL OVERRIDE { return NULL; }
   bool is_void () const FINAL OVERRIDE { return m_kind == GCC_JIT_TYPE_VOID; }
 
 public:
@@ -629,6 +633,8 @@ public:
   bool is_bool () const FINAL OVERRIDE { return false; }
   type *is_pointer () FINAL OVERRIDE { return m_other_type; }
   type *is_array () FINAL OVERRIDE { return NULL; }
+  vector_type *is_vector () FINAL OVERRIDE { return NULL; }
+  struct_ *is_struct () FINAL OVERRIDE { return NULL; }
 
 private:
   string * make_debug_string () FINAL OVERRIDE;
@@ -655,6 +661,7 @@ public:
   bool is_bool () const FINAL OVERRIDE { return m_other_type->is_bool (); }
   type *is_pointer () FINAL OVERRIDE { return m_other_type->is_pointer (); }
   type *is_array () FINAL OVERRIDE { return m_other_type->is_array (); }
+  struct_ *is_struct () FINAL OVERRIDE { return m_other_type->is_struct (); }
 
 protected:
   type *m_other_type;
@@ -737,6 +744,8 @@ public:
 
   void replay_into (replayer *) FINAL OVERRIDE;
 
+  vector_type *is_vector () FINAL OVERRIDE { return this; }
+
 private:
   string * make_debug_string () FINAL OVERRIDE;
   void write_reproducer (reproducer &r) FINAL OVERRIDE;
@@ -765,6 +774,8 @@ class array_type : public type
   bool is_bool () const FINAL OVERRIDE { return false; }
   type *is_pointer () FINAL OVERRIDE { return NULL; }
   type *is_array () FINAL OVERRIDE { return m_element_type; }
+  vector_type *is_vector () FINAL OVERRIDE { return NULL; }
+  struct_ *is_struct () FINAL OVERRIDE { return NULL; }
   int num_elements () { return m_num_elements; }
 
   void replay_into (replayer *) FINAL OVERRIDE;
@@ -799,6 +810,8 @@ public:
   bool is_bool () const FINAL OVERRIDE { return false; }
   type *is_pointer () FINAL OVERRIDE { return NULL; }
   type *is_array () FINAL OVERRIDE { return NULL; }
+  vector_type *is_vector () FINAL OVERRIDE { return NULL; }
+  struct_ *is_struct () FINAL OVERRIDE { return NULL; }
 
   void replay_into (replayer *) FINAL OVERRIDE;
 
@@ -912,6 +925,7 @@ public:
   bool is_bool () const FINAL OVERRIDE { return false; }
   type *is_pointer () FINAL OVERRIDE { return NULL; }
   type *is_array () FINAL OVERRIDE { return NULL; }
+  vector_type *is_vector () FINAL OVERRIDE { return NULL; }
 
   bool has_known_size () const FINAL OVERRIDE { return m_fields != NULL; }
 
@@ -943,6 +957,8 @@ public:
 
   const char *access_as_type (reproducer &r) FINAL OVERRIDE;
 
+  struct_ *is_struct () FINAL OVERRIDE { return this; }
+
 private:
   string * make_debug_string () FINAL OVERRIDE;
   void write_reproducer (reproducer &r) FINAL OVERRIDE;
diff --git a/gcc/jit/libgccjit.c b/gcc/jit/libgccjit.c
index a00aefc7108..94a0f1955ec 100644
--- a/gcc/jit/libgccjit.c
+++ b/gcc/jit/libgccjit.c
@@ -21,6 +21,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "config.h"
 #include "system.h"
 #include "coretypes.h"
+#include "tm.h"
 #include "timevar.h"
 #include "typed-splay-tree.h"
 #include "cppbuiltin.h"
@@ -60,6 +61,14 @@ struct gcc_jit_struct : public gcc::jit::recording::struct_
 {
 };
 
+struct gcc_jit_function_type : public gcc::jit::recording::function_type
+{
+};
+
+struct gcc_jit_vector_type : public gcc::jit::recording::vector_type
+{
+};
+
 struct gcc_jit_field : public gcc::jit::recording::field
 {
 };
@@ -510,6 +519,195 @@ gcc_jit_type_get_volatile (gcc_jit_type *type)
   return (gcc_jit_type *)type->get_volatile ();
 }
 
+/* Public entrypoint.  See description in libgccjit.h.
+
+   After error-checking, the real work is done by the
+   gcc::jit::recording::type::is_array method, in
+   jit-recording.c.  */
+
+gcc_jit_type *
+gcc_jit_type_is_array (gcc_jit_type *type)
+{
+  RETURN_NULL_IF_FAIL (type, NULL, NULL, "NULL type");
+
+  return (gcc_jit_type *)type->is_array ();
+}
+
+/* Public entrypoint.  See description in libgccjit.h.
+
+   After error-checking, the real work is done by the
+   gcc::jit::recording::type::is_bool method, in
+   jit-recording.c.  */
+
+int
+gcc_jit_type_is_bool (gcc_jit_type *type)
+{
+  RETURN_VAL_IF_FAIL (type, FALSE, NULL, NULL, "NULL type");
+
+  return type->is_bool ();
+}
+
+/* Public entrypoint.  See description in libgccjit.h.
+
+   After error-checking, the real work is done by the
+   gcc::jit::recording::type::is_pointer method, in
+   jit-recording.c.  */
+
+gcc_jit_type *
+gcc_jit_type_is_pointer (gcc_jit_type *type)
+{
+  RETURN_NULL_IF_FAIL (type, NULL, NULL, "NULL type");
+
+  return (gcc_jit_type *)type->is_pointer ();
+}
+
+/* Public entrypoint.  See description in libgccjit.h.
+
+   After error-checking, the real work is done by the
+   gcc::jit::recording::type::is_int method, in
+   jit-recording.c.  */
+
+int
+gcc_jit_type_is_int (gcc_jit_type *type)
+{
+  RETURN_VAL_IF_FAIL (type, FALSE, NULL, NULL, "NULL type");
+
+  return type->is_int ();
+}
+
+/* Public entrypoint.  See description in libgccjit.h.
+
+   After error-checking, the real work is done by the
+   gcc::jit::recording::type::is_vector method, in
+   jit-recording.c.  */
+
+gcc_jit_vector_type *
+gcc_jit_type_is_vector (gcc_jit_type *type)
+{
+  RETURN_NULL_IF_FAIL (type, NULL, NULL, "NULL type");
+  gcc::jit::recording::vector_type *vector_type = type->is_vector();
+  return (gcc_jit_vector_type *)vector_type;
+}
+
+/* Public entrypoint.  See description in libgccjit.h.
+
+   After error-checking, the real work is done by the
+   gcc::jit::recording::type::is_struct method, in
+   jit-recording.c.  */
+
+gcc_jit_struct *
+gcc_jit_type_is_struct (gcc_jit_type *type)
+{
+  RETURN_NULL_IF_FAIL (type, NULL, NULL, "NULL type");
+  gcc::jit::recording::struct_ *struct_type = type->is_struct();
+  return (gcc_jit_struct *)struct_type;
+}
+
+/* Public entrypoint.  See description in libgccjit.h.
+
+   After error-checking, the real work is done by the
+   gcc::jit::recording::vector_type::get_num_units method, in
+   jit-recording.c.  */
+
+ssize_t
+gcc_jit_vector_type_get_num_units (gcc_jit_vector_type *vector_type)
+{
+  RETURN_VAL_IF_FAIL (vector_type, -1, NULL, NULL, "NULL vector_type");
+  return vector_type->get_num_units ();
+}
+
+/* Public entrypoint.  See description in libgccjit.h.
+
+   After error-checking, the real work is done by the
+   gcc::jit::recording::vector_type::get_element_type method, in
+   jit-recording.c.  */
+
+gcc_jit_type *
+gcc_jit_vector_type_get_element_type (gcc_jit_vector_type *vector_type)
+{
+  RETURN_NULL_IF_FAIL (vector_type, NULL, NULL, "NULL vector_type");
+  return (gcc_jit_type *)vector_type->get_element_type ();
+}
+
+/* Public entrypoint.  See description in libgccjit.h.
+
+   After error-checking, the real work is done by the
+   gcc::jit::recording::type::unqualified method, in
+   jit-recording.c.  */
+
+gcc_jit_type *
+gcc_jit_type_unqualified (gcc_jit_type *type)
+{
+  RETURN_NULL_IF_FAIL (type, NULL, NULL, "NULL type");
+
+  return (gcc_jit_type *)type->unqualified ();
+}
+
+/* Public entrypoint.  See description in libgccjit.h.
+
+   After error-checking, the real work is done by the
+   gcc::jit::recording::type::dyn_cast_function_type method, in
+   jit-recording.c.  */
+
+gcc_jit_function_type *
+gcc_jit_type_is_function_ptr_type (gcc_jit_type *type)
+{
+  RETURN_NULL_IF_FAIL (type, NULL, NULL, "NULL type");
+  gcc::jit::recording::type *func_ptr_type = type->dereference ();
+  RETURN_NULL_IF_FAIL (func_ptr_type, NULL, NULL, "NULL type");
+  gcc::jit::recording::function_type *func_type = func_ptr_type->dyn_cast_function_type();
+  RETURN_NULL_IF_FAIL (func_type, NULL, NULL, "NULL type");
+
+  return (gcc_jit_function_type *)func_type;
+}
+
+/* Public entrypoint.  See description in libgccjit.h.
+
+   After error-checking, the real work is done by the
+   gcc::jit::recording::function_type::get_return_type method, in
+   jit-recording.c.  */
+
+gcc_jit_type *
+gcc_jit_function_type_get_return_type (gcc_jit_function_type *function_type)
+{
+  RETURN_NULL_IF_FAIL (function_type, NULL, NULL, "NULL struct_type");
+  return (gcc_jit_type *)function_type->get_return_type ();
+}
+
+/* Public entrypoint.  See description in libgccjit.h.
+
+   After error-checking, the real work is done by the
+   gcc::jit::recording::function_type::get_param_types method, in
+   jit-recording.c.  */
+
+ssize_t
+gcc_jit_function_type_get_param_count (gcc_jit_function_type *function_type)
+{
+  RETURN_VAL_IF_FAIL (function_type, -1, NULL, NULL, "NULL struct_type");
+  return function_type->get_param_types ().length();
+}
+
+/* Public entrypoint.  See description in libgccjit.h.
+
+   After error-checking, the real work is done by the
+   gcc::jit::recording::function_type::get_param_types method, in
+   jit-recording.c.  */
+
+gcc_jit_type *
+gcc_jit_function_type_get_param_type (gcc_jit_function_type *function_type, int index)
+{
+  RETURN_NULL_IF_FAIL (function_type, NULL, NULL, "NULL struct_type");
+  int num_params = function_type->get_param_types ().length ();
+  gcc::jit::recording::context *ctxt = function_type->m_ctxt;
+  RETURN_NULL_IF_FAIL_PRINTF3 (index < num_params,
+			       ctxt, NULL,
+			       "index of %d is too large (%s has %d params)",
+			       index,
+			       function_type->get_debug_string (),
+			       num_params);
+  return (gcc_jit_type *)function_type->get_param_types ()[index];
+}
+
 /* Public entrypoint.  See description in libgccjit.h.
 
    After error-checking, the real work is done by the
@@ -731,6 +929,33 @@ gcc_jit_struct_set_fields (gcc_jit_struct *struct_type,
 			   (gcc::jit::recording::field **)fields);
 }
 
+
+/* Public entrypoint.  See description in libgccjit.h.
+
+   After error-checking, the real work is done by the
+   gcc::jit::recording::fields::get_field method in
+   jit-recording.c.  */
+extern gcc_jit_field *
+gcc_jit_struct_get_field (gcc_jit_struct *struct_type,
+			   int index)
+{
+  RETURN_NULL_IF_FAIL (struct_type, NULL, NULL, "NULL struct type");
+  return (gcc_jit_field *)struct_type->get_fields()->get_field(index);
+}
+
+/* Public entrypoint.  See description in libgccjit.h.
+
+   After error-checking, this calls the trivial
+   gcc::jit::recording::struct_::get_fields method in
+   jit-recording.h.  */
+
+ssize_t
+gcc_jit_struct_get_field_count (gcc_jit_struct *struct_type)
+{
+  RETURN_VAL_IF_FAIL (struct_type, -1, NULL, NULL, "NULL struct type");
+  return struct_type->get_fields()->length();
+}
+
 /* Public entrypoint.  See description in libgccjit.h.
 
    After error-checking, the real work is done by the
@@ -1012,6 +1237,35 @@ gcc_jit_function_get_param (gcc_jit_function *func, int index)
   return static_cast <gcc_jit_param *> (func->get_param (index));
 }
 
+/* Public entrypoint.  See description in libgccjit.h.
+
+   After error-checking, the real work is done by the
+   gcc::jit::recording::function::get_params method, in
+   jit-recording.h.
+  */
+
+ssize_t
+gcc_jit_function_get_param_count (gcc_jit_function *func)
+{
+  RETURN_VAL_IF_FAIL (func, -1, NULL, NULL, "NULL function");
+  gcc::jit::recording::context *ctxt = func->m_ctxt;
+  JIT_LOG_FUNC (ctxt->get_logger ());
+  return func->get_params ().length ();
+}
+
+/* Public entrypoint.  See description in libgccjit.h.
+
+   After error-checking, the real work is done by the
+   gcc::jit::recording::function::get_return_type method, in
+   jit-recording.h.  */
+
+gcc_jit_type *
+gcc_jit_function_get_return_type (gcc_jit_function *func)
+{
+    RETURN_NULL_IF_FAIL (func, NULL, NULL, "NULL function");
+    return (gcc_jit_type *)func->get_return_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 7134841bb07..b0a3d941e9c 100644
--- a/gcc/jit/libgccjit.h
+++ b/gcc/jit/libgccjit.h
@@ -96,6 +96,12 @@ typedef struct gcc_jit_field gcc_jit_field;
    the layout for, or an opaque type.  */
 typedef struct gcc_jit_struct gcc_jit_struct;
 
+/* A gcc_jit_function_type encapsulates a function type.  */
+typedef struct gcc_jit_function_type gcc_jit_function_type;
+
+/* A gcc_jit_vector_type encapsulates a vector type.  */
+typedef struct gcc_jit_vector_type gcc_jit_vector_type;
+
 /* A gcc_jit_function encapsulates a function: either one that you're
    creating yourself, or a reference to one that you're dynamically
    linking to within the rest of the process.  */
@@ -586,6 +592,60 @@ gcc_jit_type_get_const (gcc_jit_type *type);
 extern gcc_jit_type *
 gcc_jit_type_get_volatile (gcc_jit_type *type);
 
+/* Given type "T", return TRUE if the type is an array.  */
+extern gcc_jit_type *
+gcc_jit_type_is_array (gcc_jit_type *type);
+
+/* Given type "T", return TRUE if the type is a bool.  */
+extern int
+gcc_jit_type_is_bool (gcc_jit_type *type);
+
+/* Given type "T", return the function type if it is one.  */
+extern gcc_jit_function_type *
+gcc_jit_type_is_function_ptr_type (gcc_jit_type *type);
+
+/* Given a function type, return its return type. */
+extern gcc_jit_type *
+gcc_jit_function_type_get_return_type (gcc_jit_function_type *function_type);
+
+/* Given a function type, return its number of parameters. */
+extern ssize_t
+gcc_jit_function_type_get_param_count (gcc_jit_function_type *function_type);
+
+/* Given a function type, return the type of the specified parameter. */
+extern gcc_jit_type *
+gcc_jit_function_type_get_param_type (gcc_jit_function_type *function_type, int index);
+
+/* Given type "T", return the type pointed by the pointer type
+ * or NULL if it's not a pointer.  */
+extern gcc_jit_type *
+gcc_jit_type_is_pointer (gcc_jit_type *type);
+
+/* Given type "T", return TRUE if the type is an int.  */
+extern int
+gcc_jit_type_is_int (gcc_jit_type *type);
+
+/* Given type "T", return the unqualified type, i.e. for a
+ * decorated type, return the type it wraps.  */
+extern gcc_jit_type *
+gcc_jit_type_unqualified (gcc_jit_type *type);
+
+/* Given type "T", return TRUE if the type is a vector type.  */
+extern gcc_jit_vector_type *
+gcc_jit_type_is_vector (gcc_jit_type *type);
+
+/* Given type "T", return the struct type or NULL.  */
+extern gcc_jit_struct *
+gcc_jit_type_is_struct (gcc_jit_type *type);
+
+/* Given a vector type, return the number of units it contains. */
+extern ssize_t
+gcc_jit_vector_type_get_num_units (gcc_jit_vector_type *vector_type);
+
+/* Given a vector type, return the type of its elements. */
+extern gcc_jit_type *
+gcc_jit_vector_type_get_element_type (gcc_jit_vector_type *vector_type);
+
 /* Given type "T", get type "T[N]" (for a constant N).  */
 extern gcc_jit_type *
 gcc_jit_context_new_array_type (gcc_jit_context *ctxt,
@@ -647,6 +707,15 @@ gcc_jit_struct_set_fields (gcc_jit_struct *struct_type,
 			   int num_fields,
 			   gcc_jit_field **fields);
 
+/* Get a field by index. */
+extern gcc_jit_field *
+gcc_jit_struct_get_field (gcc_jit_struct *struct_type,
+			   int index);
+
+/* Get the number of fields. */
+extern ssize_t
+gcc_jit_struct_get_field_count (gcc_jit_struct *struct_type);
+
 /* Unions work similarly to structs.  */
 extern gcc_jit_type *
 gcc_jit_context_new_union_type (gcc_jit_context *ctxt,
@@ -740,6 +809,14 @@ gcc_jit_function_as_object (gcc_jit_function *func);
 extern gcc_jit_param *
 gcc_jit_function_get_param (gcc_jit_function *func, int index);
 
+/* Get the number of params of a function.  */
+extern ssize_t
+gcc_jit_function_get_param_count (gcc_jit_function *func);
+
+/* Get the return type of a function.  */
+extern gcc_jit_type *
+gcc_jit_function_get_return_type (gcc_jit_function *func);
+
 /* Emit the function in graphviz format.  */
 extern void
 gcc_jit_function_dump_to_dot (gcc_jit_function *func,
@@ -1518,6 +1595,46 @@ gcc_jit_version_minor (void);
 extern int
 gcc_jit_version_patchlevel (void);
 
+#define LIBGCCJIT_HAVE_gcc_jit_function_reflection
+
+/* Reflection functions to get the number of parameters, return type of
+   a function and whether a type is a bool from the C API.
+
+   This API entrypoint was added in LIBGCCJIT_ABI_15; you can test for its
+   presence using
+     #ifdef LIBGCCJIT_HAVE_gcc_jit_function_reflection
+*/
+extern gcc_jit_type *
+gcc_jit_function_get_return_type (gcc_jit_function *func);
+extern ssize_t
+gcc_jit_function_get_param_count (gcc_jit_function *func);
+extern gcc_jit_type *
+gcc_jit_type_is_array (gcc_jit_type *type);
+extern int
+gcc_jit_type_is_bool (gcc_jit_type *type);
+extern gcc_jit_function_type *
+gcc_jit_type_is_function_ptr_type (gcc_jit_type *type);
+extern gcc_jit_type *
+gcc_jit_function_type_get_return_type (gcc_jit_function_type *function_type);
+extern ssize_t
+gcc_jit_function_type_get_param_count (gcc_jit_function_type *function_type);
+extern gcc_jit_type *
+gcc_jit_function_type_get_param_type (gcc_jit_function_type *function_type, int index);
+extern int
+gcc_jit_type_is_int (gcc_jit_type *type);
+extern gcc_jit_type *
+gcc_jit_type_is_pointer (gcc_jit_type *type);
+extern gcc_jit_vector_type *
+gcc_jit_type_is_vector (gcc_jit_type *type);
+extern gcc_jit_struct *
+gcc_jit_type_is_struct (gcc_jit_type *type);
+extern ssize_t
+gcc_jit_vector_type_get_num_units (gcc_jit_vector_type *vector_type);
+extern gcc_jit_type *
+gcc_jit_vector_type_get_element_type (gcc_jit_vector_type *vector_type);
+extern gcc_jit_type *
+gcc_jit_type_unqualified (gcc_jit_type *type);
+
 #ifdef __cplusplus
 }
 #endif /* __cplusplus */
diff --git a/gcc/jit/libgccjit.map b/gcc/jit/libgccjit.map
index a6e67e781a4..84d40f5a636 100644
--- a/gcc/jit/libgccjit.map
+++ b/gcc/jit/libgccjit.map
@@ -192,3 +192,24 @@ LIBGCCJIT_ABI_14 {
   global:
     gcc_jit_global_set_initializer;
 } LIBGCCJIT_ABI_13;
+
+LIBGCCJIT_ABI_15 {
+  global:
+    gcc_jit_function_get_return_type;
+    gcc_jit_function_get_param_count;
+    gcc_jit_function_type_get_return_type;
+    gcc_jit_function_type_get_param_count;
+    gcc_jit_function_type_get_param_type;
+    gcc_jit_type_unqualified;
+    gcc_jit_type_is_array;
+    gcc_jit_type_is_bool;
+    gcc_jit_type_is_function_ptr_type;
+    gcc_jit_type_is_int;
+    gcc_jit_type_is_pointer;
+    gcc_jit_type_is_vector;
+    gcc_jit_vector_type_get_element_type;
+    gcc_jit_vector_type_get_num_units;
+    gcc_jit_struct_get_field;
+    gcc_jit_type_is_struct;
+    gcc_jit_struct_get_field_count;
+} LIBGCCJIT_ABI_14;
diff --git a/gcc/testsuite/jit.dg/all-non-failing-tests.h b/gcc/testsuite/jit.dg/all-non-failing-tests.h
index 4202eb7798b..a269144d2df 100644
--- a/gcc/testsuite/jit.dg/all-non-failing-tests.h
+++ b/gcc/testsuite/jit.dg/all-non-failing-tests.h
@@ -258,6 +258,13 @@
 #undef create_code
 #undef verify_code
 
+/* test-reflection.c */
+#define create_code create_code_reflection
+#define verify_code verify_code_reflection
+#include "test-reflection.c"
+#undef create_code
+#undef verify_code
+
 /* test-string-literal.c */
 #define create_code create_code_string_literal
 #define verify_code verify_code_string_literal
@@ -424,6 +431,9 @@ const struct testcase testcases[] = {
   {"reading_struct ",
    create_code_reading_struct ,
    verify_code_reading_struct },
+  {"reflection",
+   create_code_reflection ,
+   verify_code_reflection },
   {"string_literal",
    create_code_string_literal,
    verify_code_string_literal},
diff --git a/gcc/testsuite/jit.dg/test-reflection.c b/gcc/testsuite/jit.dg/test-reflection.c
new file mode 100644
index 00000000000..40a5c43076d
--- /dev/null
+++ b/gcc/testsuite/jit.dg/test-reflection.c
@@ -0,0 +1,89 @@
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "libgccjit.h"
+
+#include "harness.h"
+
+void
+create_code (gcc_jit_context *ctxt, void *user_data)
+{
+  /* Do nothing.  */
+}
+
+void
+verify_code (gcc_jit_context *ctxt, gcc_jit_result *result)
+{
+  /* Get the built-in functions.  */
+  gcc_jit_function *builtin_sin =
+    gcc_jit_context_get_builtin_function (ctxt, "sin");
+
+  CHECK_VALUE (gcc_jit_function_get_param_count(builtin_sin), 1);
+
+  gcc_jit_type *double_type =
+    gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_DOUBLE);
+  CHECK_VALUE (gcc_jit_function_get_return_type(builtin_sin), double_type);
+  CHECK (!gcc_jit_type_is_int(double_type));
+
+  gcc_jit_type *bool_type =
+    gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_BOOL);
+  CHECK (gcc_jit_type_is_bool(bool_type));
+  CHECK (!gcc_jit_type_is_int(bool_type));
+
+  gcc_jit_type *aligned_bool_type =
+    gcc_jit_type_get_aligned(gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_BOOL), 8);
+  CHECK (gcc_jit_type_is_bool(aligned_bool_type));
+  CHECK (bool_type != aligned_bool_type);
+  CHECK_VALUE (gcc_jit_type_unqualified(aligned_bool_type), bool_type);
+
+  CHECK_VALUE (gcc_jit_type_unqualified(gcc_jit_type_get_const(bool_type)), bool_type);
+  CHECK_VALUE (gcc_jit_type_unqualified(gcc_jit_type_get_volatile(bool_type)), bool_type);
+
+  gcc_jit_type *int64 =
+    gcc_jit_context_get_int_type(ctxt, 8, 1);
+  CHECK (gcc_jit_type_is_int(int64));
+  gcc_jit_type *uint64 =
+    gcc_jit_context_get_int_type(ctxt, 8, 0);
+  CHECK (gcc_jit_type_is_int(uint64));
+  gcc_jit_type *int8 =
+    gcc_jit_context_get_int_type(ctxt, 1, 1);
+  CHECK (gcc_jit_type_is_int(int8));
+  gcc_jit_type *uint8 =
+    gcc_jit_context_get_int_type(ctxt, 1, 0);
+  CHECK (gcc_jit_type_is_int(uint8));
+
+  CHECK (!gcc_jit_type_is_vector(double_type));
+  gcc_jit_type *vec_type = gcc_jit_type_get_vector (double_type, 4);
+  gcc_jit_vector_type *vector_type = gcc_jit_type_is_vector(vec_type);
+  CHECK (vector_type);
+  CHECK (vec_type != double_type);
+  CHECK_VALUE (gcc_jit_vector_type_get_element_type(vector_type), double_type);
+  CHECK_VALUE (gcc_jit_vector_type_get_num_units(vector_type), 4);
+
+  CHECK (!gcc_jit_type_is_pointer(double_type));
+  CHECK_VALUE (gcc_jit_type_is_pointer(gcc_jit_type_get_pointer(double_type)), double_type);
+
+  gcc_jit_type* params[2] = {int8, uint64};
+  gcc_jit_type *function_ptr_type = gcc_jit_context_new_function_ptr_type(ctxt, NULL, int64, 2, params, 0);
+  gcc_jit_function_type *function_type = gcc_jit_type_is_function_ptr_type (function_ptr_type);
+  CHECK (function_type);
+  int param_count = gcc_jit_function_type_get_param_count(function_type);
+  CHECK_VALUE (param_count, 2);
+  gcc_jit_type *return_type = gcc_jit_function_type_get_return_type(function_type);
+  CHECK_VALUE (return_type, int64);
+  gcc_jit_type *param1 = gcc_jit_function_type_get_param_type(function_type, 0);
+  CHECK_VALUE (param1, int8);
+  gcc_jit_type *param2 = gcc_jit_function_type_get_param_type(function_type, 1);
+  CHECK_VALUE (param2, uint64);
+
+  gcc_jit_field *field1 = gcc_jit_context_new_field (ctxt, NULL, uint64, "field1");
+  gcc_jit_field *field2 = gcc_jit_context_new_field (ctxt, NULL, double_type, "field2");
+  gcc_jit_field *fields[2] = { field1, field2 };
+  gcc_jit_struct *struct_type = gcc_jit_context_new_struct_type (ctxt, NULL, "testStruct", 2, fields);
+  CHECK_VALUE (gcc_jit_struct_get_field_count(struct_type), 2);
+  CHECK_VALUE (gcc_jit_struct_get_field(struct_type, 0), field1);
+  CHECK_VALUE (gcc_jit_struct_get_field(struct_type, 1), field2);
+  gcc_jit_struct *struct_ty = gcc_jit_type_is_struct(gcc_jit_struct_as_type(struct_type));
+  CHECK_VALUE (struct_ty, struct_type);
+}
+
-- 
2.28.0


^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re: [PATCH] libgccjit: add some reflection functions in the jit C api
  2020-10-15 16:02     ` [PATCH] libgccjit: add some reflection functions in the jit C api Antoni Boucher
@ 2020-10-15 16:23       ` Andrea Corallo
  2020-10-15 17:39         ` Antoni Boucher
  0 siblings, 1 reply; 35+ messages in thread
From: Andrea Corallo @ 2020-10-15 16:23 UTC (permalink / raw)
  To: Antoni Boucher via Jit; +Cc: David Malcolm, Antoni Boucher, gcc-patches

Antoni Boucher via Jit <jit@gcc.gnu.org> writes:

Hi Antoni,

Just had a quick look, please find some quite minor comments in line.

> From b0edc9eb8e8d3ba9e1c6a8d061a8627c0b0cf102 Mon Sep 17 00:00:00 2001
> From: Antoni Boucher <bouanto@zoho.com>
> Date: Sat, 1 Aug 2020 17:52:17 -0400
> Subject: [PATCH] This patch add some reflection functions in the jit C api
>  [PR96889]
>
> 2020-09-1  Antoni Boucher  <bouanto@zoho.com>
>
>     gcc/jit/
>             PR target/96889
>             * docs/topics/compatibility.rst (LIBGCCJIT_ABI_14): New ABI tag.
>             * docs/topics/functions.rst: Add documentation for the
>             functions gcc_jit_function_get_return_type and
>             gcc_jit_function_get_param_count
>             * libgccjit.c: New functions:
>               * gcc_jit_function_get_return_type;
>               * gcc_jit_function_get_param_count;
>               * gcc_jit_function_type_get_return_type;
>               * gcc_jit_function_type_get_param_count;
>               * gcc_jit_function_type_get_param_type;
>               * gcc_jit_type_unqualified;
>               * gcc_jit_type_is_array;
>               * gcc_jit_type_is_bool;
>               * gcc_jit_type_is_function_ptr_type;
>               * gcc_jit_type_is_int;
>               * gcc_jit_type_is_pointer;
>               * gcc_jit_type_is_vector;
>               * gcc_jit_vector_type_get_element_type;
>               * gcc_jit_vector_type_get_num_units;
>               * gcc_jit_struct_get_field;
>               * gcc_jit_type_is_struct;
>               * gcc_jit_struct_get_field_count;
>             * libgccjit.h
>             * jit-recording.h: New functions (is_struct and is_vector)
>             * libgccjit.map (LIBGCCJIT_ABI_14): New ABI tag.
>
>     gcc/testsuite/
>             PR target/96889
>             * jit.dg/all-non-failing-tests.h: Add test-reflection.c.
>             * jit.dg/test-reflection.c: New test.
> ---
>  gcc/jit/docs/topics/compatibility.rst        |  41 +++
>  gcc/jit/docs/topics/functions.rst            |  10 +
>  gcc/jit/jit-recording.h                      |  16 ++
>  gcc/jit/libgccjit.c                          | 254 +++++++++++++++++++
>  gcc/jit/libgccjit.h                          | 117 +++++++++
>  gcc/jit/libgccjit.map                        |  21 ++
>  gcc/testsuite/jit.dg/all-non-failing-tests.h |  10 +
>  gcc/testsuite/jit.dg/test-reflection.c       |  89 +++++++
>  8 files changed, 558 insertions(+)
>  create mode 100644 gcc/testsuite/jit.dg/test-reflection.c
>
> diff --git a/gcc/jit/docs/topics/compatibility.rst b/gcc/jit/docs/topics/compatibility.rst
> index 6bfa101ed71..16f24d20a75 100644
> --- a/gcc/jit/docs/topics/compatibility.rst
> +++ b/gcc/jit/docs/topics/compatibility.rst
> @@ -226,3 +226,44 @@ entrypoints:
>  --------------------
>  ``LIBGCCJIT_ABI_14`` covers the addition of
>  :func:`gcc_jit_global_set_initializer`
> +
> +.. _LIBGCCJIT_ABI_15:
> +
> +``LIBGCCJIT_ABI_15``
> +--------------------
> +``LIBGCCJIT_ABI_15`` covers the addition of reflection functions via API
> +entrypoints:
> +
> +  * :func:`gcc_jit_function_get_return_type`
> +
> +  * :func:`gcc_jit_function_get_param_count`
> +
> +  * :func:`gcc_jit_type_is_array`
> +
> +  * :func:`gcc_jit_type_is_bool`
> +
> +  * :func:`gcc_jit_type_is_int`
> +
> +  * :func:`gcc_jit_type_is_pointer`
> +
> +  * :func:`gcc_jit_type_is_struct`
> +
> +  * :func:`gcc_jit_type_is_vector`
> +
> +  * :func:`gcc_jit_type_unqualified`
> +
> +  * :func:`gcc_jit_type_is_function_ptr_type`
> +
> +  * :func:`gcc_jit_function_type_get_return_type`
> +
> +  * :func:`gcc_jit_function_type_get_param_count`
> +
> +  * :func:`gcc_jit_function_type_get_param_type`
> +
> +  * :func:`gcc_jit_vector_type_get_num_units`
> +
> +  * :func:`gcc_jit_vector_type_get_element_type`
> +
> +  * :func:`gcc_jit_struct_get_field`
> +
> +  * :func:`gcc_jit_struct_get_field_count`
> diff --git a/gcc/jit/docs/topics/functions.rst b/gcc/jit/docs/topics/functions.rst
> index eb40d64010e..9819c28cda2 100644
> --- a/gcc/jit/docs/topics/functions.rst
> +++ b/gcc/jit/docs/topics/functions.rst
> @@ -171,6 +171,16 @@ Functions
>     underlying string, so it is valid to pass in a pointer to an on-stack
>     buffer.
>  
> +.. function::  size_t \
> +               gcc_jit_function_get_param_count (gcc_jit_function *func)
> +
> +   Get the number of parameters of the function.
> +
> +.. function::  gcc_jit_type \*
> +               gcc_jit_function_get_return_type (gcc_jit_function *func)
> +
> +   Get the return type of the function.
> +
>  Blocks
>  ------
>  .. type:: gcc_jit_block
> diff --git a/gcc/jit/jit-recording.h b/gcc/jit/jit-recording.h
> index 30e37aff387..525b8bc921d 100644
> --- a/gcc/jit/jit-recording.h
> +++ b/gcc/jit/jit-recording.h
> @@ -538,7 +538,9 @@ public:
>    virtual bool is_bool () const = 0;
>    virtual type *is_pointer () = 0;
>    virtual type *is_array () = 0;
> +  virtual struct_ *is_struct () { return NULL; }
>    virtual bool is_void () const { return false; }
> +  virtual vector_type *is_vector () { return NULL; }
>    virtual bool has_known_size () const { return true; }
>  
>    bool is_numeric () const
> @@ -595,6 +597,8 @@ public:
>    bool is_bool () const FINAL OVERRIDE;
>    type *is_pointer () FINAL OVERRIDE { return dereference (); }
>    type *is_array () FINAL OVERRIDE { return NULL; }
> +  vector_type *is_vector () FINAL OVERRIDE { return NULL; }
> +  struct_ *is_struct () FINAL OVERRIDE { return NULL; }
>    bool is_void () const FINAL OVERRIDE { return m_kind == GCC_JIT_TYPE_VOID; }
>  
>  public:
> @@ -629,6 +633,8 @@ public:
>    bool is_bool () const FINAL OVERRIDE { return false; }
>    type *is_pointer () FINAL OVERRIDE { return m_other_type; }
>    type *is_array () FINAL OVERRIDE { return NULL; }
> +  vector_type *is_vector () FINAL OVERRIDE { return NULL; }
> +  struct_ *is_struct () FINAL OVERRIDE { return NULL; }
>  
>  private:
>    string * make_debug_string () FINAL OVERRIDE;
> @@ -655,6 +661,7 @@ public:
>    bool is_bool () const FINAL OVERRIDE { return m_other_type->is_bool (); }
>    type *is_pointer () FINAL OVERRIDE { return m_other_type->is_pointer (); }
>    type *is_array () FINAL OVERRIDE { return m_other_type->is_array (); }
> +  struct_ *is_struct () FINAL OVERRIDE { return m_other_type->is_struct (); }
>  
>  protected:
>    type *m_other_type;
> @@ -737,6 +744,8 @@ public:
>  
>    void replay_into (replayer *) FINAL OVERRIDE;
>  
> +  vector_type *is_vector () FINAL OVERRIDE { return this; }
> +
>  private:
>    string * make_debug_string () FINAL OVERRIDE;
>    void write_reproducer (reproducer &r) FINAL OVERRIDE;
> @@ -765,6 +774,8 @@ class array_type : public type
>    bool is_bool () const FINAL OVERRIDE { return false; }
>    type *is_pointer () FINAL OVERRIDE { return NULL; }
>    type *is_array () FINAL OVERRIDE { return m_element_type; }
> +  vector_type *is_vector () FINAL OVERRIDE { return NULL; }
> +  struct_ *is_struct () FINAL OVERRIDE { return NULL; }
>    int num_elements () { return m_num_elements; }
>  
>    void replay_into (replayer *) FINAL OVERRIDE;
> @@ -799,6 +810,8 @@ public:
>    bool is_bool () const FINAL OVERRIDE { return false; }
>    type *is_pointer () FINAL OVERRIDE { return NULL; }
>    type *is_array () FINAL OVERRIDE { return NULL; }
> +  vector_type *is_vector () FINAL OVERRIDE { return NULL; }
> +  struct_ *is_struct () FINAL OVERRIDE { return NULL; }
>  
>    void replay_into (replayer *) FINAL OVERRIDE;
>  
> @@ -912,6 +925,7 @@ public:
>    bool is_bool () const FINAL OVERRIDE { return false; }
>    type *is_pointer () FINAL OVERRIDE { return NULL; }
>    type *is_array () FINAL OVERRIDE { return NULL; }
> +  vector_type *is_vector () FINAL OVERRIDE { return NULL; }
>  
>    bool has_known_size () const FINAL OVERRIDE { return m_fields != NULL; }
>  
> @@ -943,6 +957,8 @@ public:
>  
>    const char *access_as_type (reproducer &r) FINAL OVERRIDE;
>  
> +  struct_ *is_struct () FINAL OVERRIDE { return this; }
> +
>  private:
>    string * make_debug_string () FINAL OVERRIDE;
>    void write_reproducer (reproducer &r) FINAL OVERRIDE;
> diff --git a/gcc/jit/libgccjit.c b/gcc/jit/libgccjit.c
> index a00aefc7108..94a0f1955ec 100644
> --- a/gcc/jit/libgccjit.c
> +++ b/gcc/jit/libgccjit.c
> @@ -21,6 +21,7 @@ along with GCC; see the file COPYING3.  If not see
>  #include "config.h"
>  #include "system.h"
>  #include "coretypes.h"
> +#include "tm.h"
>  #include "timevar.h"
>  #include "typed-splay-tree.h"
>  #include "cppbuiltin.h"
> @@ -60,6 +61,14 @@ struct gcc_jit_struct : public gcc::jit::recording::struct_
>  {
>  };
>  
> +struct gcc_jit_function_type : public gcc::jit::recording::function_type
> +{
> +};
> +
> +struct gcc_jit_vector_type : public gcc::jit::recording::vector_type
> +{
> +};
> +
>  struct gcc_jit_field : public gcc::jit::recording::field
>  {
>  };
> @@ -510,6 +519,195 @@ gcc_jit_type_get_volatile (gcc_jit_type *type)
>    return (gcc_jit_type *)type->get_volatile ();
>  }
>  
> +/* Public entrypoint.  See description in libgccjit.h.
> +
> +   After error-checking, the real work is done by the
> +   gcc::jit::recording::type::is_array method, in
> +   jit-recording.c.  */
> +
> +gcc_jit_type *
> +gcc_jit_type_is_array (gcc_jit_type *type)
> +{
> +  RETURN_NULL_IF_FAIL (type, NULL, NULL, "NULL type");
> +
> +  return (gcc_jit_type *)type->is_array ();
> +}
> +
> +/* Public entrypoint.  See description in libgccjit.h.
> +
> +   After error-checking, the real work is done by the
> +   gcc::jit::recording::type::is_bool method, in
> +   jit-recording.c.  */
> +
> +int
> +gcc_jit_type_is_bool (gcc_jit_type *type)
> +{
> +  RETURN_VAL_IF_FAIL (type, FALSE, NULL, NULL, "NULL type");
> +
> +  return type->is_bool ();
> +}
> +
> +/* Public entrypoint.  See description in libgccjit.h.
> +
> +   After error-checking, the real work is done by the
> +   gcc::jit::recording::type::is_pointer method, in
> +   jit-recording.c.  */
> +
> +gcc_jit_type *
> +gcc_jit_type_is_pointer (gcc_jit_type *type)
> +{
> +  RETURN_NULL_IF_FAIL (type, NULL, NULL, "NULL type");
> +
> +  return (gcc_jit_type *)type->is_pointer ();
> +}
> +
> +/* Public entrypoint.  See description in libgccjit.h.
> +
> +   After error-checking, the real work is done by the
> +   gcc::jit::recording::type::is_int method, in
> +   jit-recording.c.  */
> +
> +int
> +gcc_jit_type_is_int (gcc_jit_type *type)
> +{
> +  RETURN_VAL_IF_FAIL (type, FALSE, NULL, NULL, "NULL type");
> +
> +  return type->is_int ();
> +}
> +
> +/* Public entrypoint.  See description in libgccjit.h.
> +
> +   After error-checking, the real work is done by the
> +   gcc::jit::recording::type::is_vector method, in
> +   jit-recording.c.  */
> +
> +gcc_jit_vector_type *
> +gcc_jit_type_is_vector (gcc_jit_type *type)
> +{
> +  RETURN_NULL_IF_FAIL (type, NULL, NULL, "NULL type");
> +  gcc::jit::recording::vector_type *vector_type = type->is_vector();
                                                                   ^^^
                                                                 space here
> +  return (gcc_jit_vector_type *)vector_type;
> +}
> +
> +/* Public entrypoint.  See description in libgccjit.h.
> +
> +   After error-checking, the real work is done by the
> +   gcc::jit::recording::type::is_struct method, in
> +   jit-recording.c.  */
> +
> +gcc_jit_struct *
> +gcc_jit_type_is_struct (gcc_jit_type *type)
> +{
> +  RETURN_NULL_IF_FAIL (type, NULL, NULL, "NULL type");
> +  gcc::jit::recording::struct_ *struct_type = type->is_struct();

Likewise

> +  return (gcc_jit_struct *)struct_type;
> +}
> +
> +/* Public entrypoint.  See description in libgccjit.h.
> +
> +   After error-checking, the real work is done by the
> +   gcc::jit::recording::vector_type::get_num_units method, in
> +   jit-recording.c.  */
> +
> +ssize_t
> +gcc_jit_vector_type_get_num_units (gcc_jit_vector_type *vector_type)
> +{
> +  RETURN_VAL_IF_FAIL (vector_type, -1, NULL, NULL, "NULL vector_type");
> +  return vector_type->get_num_units ();
> +}
> +
> +/* Public entrypoint.  See description in libgccjit.h.
> +
> +   After error-checking, the real work is done by the
> +   gcc::jit::recording::vector_type::get_element_type method, in
> +   jit-recording.c.  */
> +
> +gcc_jit_type *
> +gcc_jit_vector_type_get_element_type (gcc_jit_vector_type *vector_type)
> +{
> +  RETURN_NULL_IF_FAIL (vector_type, NULL, NULL, "NULL vector_type");
> +  return (gcc_jit_type *)vector_type->get_element_type ();
> +}
> +
> +/* Public entrypoint.  See description in libgccjit.h.
> +
> +   After error-checking, the real work is done by the
> +   gcc::jit::recording::type::unqualified method, in
> +   jit-recording.c.  */
> +
> +gcc_jit_type *
> +gcc_jit_type_unqualified (gcc_jit_type *type)
> +{
> +  RETURN_NULL_IF_FAIL (type, NULL, NULL, "NULL type");
> +
> +  return (gcc_jit_type *)type->unqualified ();
> +}
> +
> +/* Public entrypoint.  See description in libgccjit.h.
> +
> +   After error-checking, the real work is done by the
> +   gcc::jit::recording::type::dyn_cast_function_type method, in
> +   jit-recording.c.  */
> +
> +gcc_jit_function_type *
> +gcc_jit_type_is_function_ptr_type (gcc_jit_type *type)
> +{
> +  RETURN_NULL_IF_FAIL (type, NULL, NULL, "NULL type");
> +  gcc::jit::recording::type *func_ptr_type = type->dereference ();
> +  RETURN_NULL_IF_FAIL (func_ptr_type, NULL, NULL, "NULL type");
> +  gcc::jit::recording::function_type *func_type = func_ptr_type->dyn_cast_function_type();

Likewise (also exceeded 80 characters).

> +  RETURN_NULL_IF_FAIL (func_type, NULL, NULL, "NULL type");
> +
> +  return (gcc_jit_function_type *)func_type;
> +}
> +
> +/* Public entrypoint.  See description in libgccjit.h.
> +
> +   After error-checking, the real work is done by the
> +   gcc::jit::recording::function_type::get_return_type method, in
> +   jit-recording.c.  */
> +
> +gcc_jit_type *
> +gcc_jit_function_type_get_return_type (gcc_jit_function_type *function_type)
> +{
> +  RETURN_NULL_IF_FAIL (function_type, NULL, NULL, "NULL struct_type");
> +  return (gcc_jit_type *)function_type->get_return_type ();
> +}
> +
> +/* Public entrypoint.  See description in libgccjit.h.
> +
> +   After error-checking, the real work is done by the
> +   gcc::jit::recording::function_type::get_param_types method, in
> +   jit-recording.c.  */
> +
> +ssize_t
> +gcc_jit_function_type_get_param_count (gcc_jit_function_type *function_type)
> +{
> +  RETURN_VAL_IF_FAIL (function_type, -1, NULL, NULL, "NULL struct_type");
> +  return function_type->get_param_types ().length();

Likewise

> +}
> +
> +/* Public entrypoint.  See description in libgccjit.h.
> +
> +   After error-checking, the real work is done by the
> +   gcc::jit::recording::function_type::get_param_types method, in
> +   jit-recording.c.  */
> +
> +gcc_jit_type *
> +gcc_jit_function_type_get_param_type (gcc_jit_function_type *function_type, int index)

Excedes 80 characters

> +{
> +  RETURN_NULL_IF_FAIL (function_type, NULL, NULL, "NULL struct_type");
> +  int num_params = function_type->get_param_types ().length ();
> +  gcc::jit::recording::context *ctxt = function_type->m_ctxt;
> +  RETURN_NULL_IF_FAIL_PRINTF3 (index < num_params,
> +			       ctxt, NULL,
> +			       "index of %d is too large (%s has %d params)",
> +			       index,
> +			       function_type->get_debug_string (),
> +			       num_params);
> +  return (gcc_jit_type *)function_type->get_param_types ()[index];
> +}
> +
>  /* Public entrypoint.  See description in libgccjit.h.
>  
>     After error-checking, the real work is done by the
> @@ -731,6 +929,33 @@ gcc_jit_struct_set_fields (gcc_jit_struct *struct_type,
>  			   (gcc::jit::recording::field **)fields);
>  }
>  
> +
> +/* Public entrypoint.  See description in libgccjit.h.
> +
> +   After error-checking, the real work is done by the
> +   gcc::jit::recording::fields::get_field method in
> +   jit-recording.c.  */
> +extern gcc_jit_field *
> +gcc_jit_struct_get_field (gcc_jit_struct *struct_type,
> +			   int index)
> +{
> +  RETURN_NULL_IF_FAIL (struct_type, NULL, NULL, "NULL struct type");
> +  return (gcc_jit_field *)struct_type->get_fields()->get_field(index);

Space before (

> +}
> +
> +/* Public entrypoint.  See description in libgccjit.h.
> +
> +   After error-checking, this calls the trivial
> +   gcc::jit::recording::struct_::get_fields method in
> +   jit-recording.h.  */
> +
> +ssize_t
> +gcc_jit_struct_get_field_count (gcc_jit_struct *struct_type)
> +{
> +  RETURN_VAL_IF_FAIL (struct_type, -1, NULL, NULL, "NULL struct type");
> +  return struct_type->get_fields()->length();

Likewise

> +}
> +
>  /* Public entrypoint.  See description in libgccjit.h.
>  
>     After error-checking, the real work is done by the
> @@ -1012,6 +1237,35 @@ gcc_jit_function_get_param (gcc_jit_function *func, int index)
>    return static_cast <gcc_jit_param *> (func->get_param (index));
>  }
>  
> +/* Public entrypoint.  See description in libgccjit.h.
> +
> +   After error-checking, the real work is done by the
> +   gcc::jit::recording::function::get_params method, in
> +   jit-recording.h.
> +  */
> +
> +ssize_t
> +gcc_jit_function_get_param_count (gcc_jit_function *func)
> +{
> +  RETURN_VAL_IF_FAIL (func, -1, NULL, NULL, "NULL function");
> +  gcc::jit::recording::context *ctxt = func->m_ctxt;
> +  JIT_LOG_FUNC (ctxt->get_logger ());
> +  return func->get_params ().length ();
> +}
> +
> +/* Public entrypoint.  See description in libgccjit.h.
> +
> +   After error-checking, the real work is done by the
> +   gcc::jit::recording::function::get_return_type method, in
> +   jit-recording.h.  */
> +
> +gcc_jit_type *
> +gcc_jit_function_get_return_type (gcc_jit_function *func)
> +{
> +    RETURN_NULL_IF_FAIL (func, NULL, NULL, "NULL function");
> +    return (gcc_jit_type *)func->get_return_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 7134841bb07..b0a3d941e9c 100644
> --- a/gcc/jit/libgccjit.h
> +++ b/gcc/jit/libgccjit.h
> @@ -96,6 +96,12 @@ typedef struct gcc_jit_field gcc_jit_field;
>     the layout for, or an opaque type.  */
>  typedef struct gcc_jit_struct gcc_jit_struct;
>  
> +/* A gcc_jit_function_type encapsulates a function type.  */
> +typedef struct gcc_jit_function_type gcc_jit_function_type;
> +
> +/* A gcc_jit_vector_type encapsulates a vector type.  */
> +typedef struct gcc_jit_vector_type gcc_jit_vector_type;
> +
>  /* A gcc_jit_function encapsulates a function: either one that you're
>     creating yourself, or a reference to one that you're dynamically
>     linking to within the rest of the process.  */
> @@ -586,6 +592,60 @@ gcc_jit_type_get_const (gcc_jit_type *type);
>  extern gcc_jit_type *
>  gcc_jit_type_get_volatile (gcc_jit_type *type);
>  
> +/* Given type "T", return TRUE if the type is an array.  */
> +extern gcc_jit_type *
> +gcc_jit_type_is_array (gcc_jit_type *type);
> +
> +/* Given type "T", return TRUE if the type is a bool.  */
> +extern int
> +gcc_jit_type_is_bool (gcc_jit_type *type);
> +
> +/* Given type "T", return the function type if it is one.  */
> +extern gcc_jit_function_type *
> +gcc_jit_type_is_function_ptr_type (gcc_jit_type *type);
> +
> +/* Given a function type, return its return type. */

GNU stile wants dot + 2 spaces at the end of a comment.

> +extern gcc_jit_type *
> +gcc_jit_function_type_get_return_type (gcc_jit_function_type *function_type);
> +
> +/* Given a function type, return its number of parameters. */

Likewise

> +extern ssize_t
> +gcc_jit_function_type_get_param_count (gcc_jit_function_type *function_type);
> +
> +/* Given a function type, return the type of the specified parameter. */

Likewise

> +extern gcc_jit_type *
> +gcc_jit_function_type_get_param_type (gcc_jit_function_type *function_type, int index);

Exceeds 80 characters

> +
> +/* Given type "T", return the type pointed by the pointer type
> + * or NULL if it's not a pointer.  */
> +extern gcc_jit_type *
> +gcc_jit_type_is_pointer (gcc_jit_type *type);
> +
> +/* Given type "T", return TRUE if the type is an int.  */
> +extern int
> +gcc_jit_type_is_int (gcc_jit_type *type);
> +
> +/* Given type "T", return the unqualified type, i.e. for a
> + * decorated type, return the type it wraps.  */
> +extern gcc_jit_type *
> +gcc_jit_type_unqualified (gcc_jit_type *type);
> +
> +/* Given type "T", return TRUE if the type is a vector type.  */
> +extern gcc_jit_vector_type *
> +gcc_jit_type_is_vector (gcc_jit_type *type);
> +
> +/* Given type "T", return the struct type or NULL.  */
> +extern gcc_jit_struct *
> +gcc_jit_type_is_struct (gcc_jit_type *type);
> +
> +/* Given a vector type, return the number of units it contains. */

One space more before */

> +extern ssize_t
> +gcc_jit_vector_type_get_num_units (gcc_jit_vector_type *vector_type);
> +
> +/* Given a vector type, return the type of its elements. */

Likewise

> +extern gcc_jit_type *
> +gcc_jit_vector_type_get_element_type (gcc_jit_vector_type *vector_type);
> +
>  /* Given type "T", get type "T[N]" (for a constant N).  */
>  extern gcc_jit_type *
>  gcc_jit_context_new_array_type (gcc_jit_context *ctxt,
> @@ -647,6 +707,15 @@ gcc_jit_struct_set_fields (gcc_jit_struct *struct_type,
>  			   int num_fields,
>  			   gcc_jit_field **fields);
>  
> +/* Get a field by index. */

Likewise

> +extern gcc_jit_field *
> +gcc_jit_struct_get_field (gcc_jit_struct *struct_type,
> +			   int index);
> +
> +/* Get the number of fields. */

Likewise

> +extern ssize_t
> +gcc_jit_struct_get_field_count (gcc_jit_struct *struct_type);
> +
>  /* Unions work similarly to structs.  */
>  extern gcc_jit_type *
>  gcc_jit_context_new_union_type (gcc_jit_context *ctxt,
> @@ -740,6 +809,14 @@ gcc_jit_function_as_object (gcc_jit_function *func);
>  extern gcc_jit_param *
>  gcc_jit_function_get_param (gcc_jit_function *func, int index);
>  
> +/* Get the number of params of a function.  */
> +extern ssize_t
> +gcc_jit_function_get_param_count (gcc_jit_function *func);
> +
> +/* Get the return type of a function.  */
> +extern gcc_jit_type *
> +gcc_jit_function_get_return_type (gcc_jit_function *func);
> +
>  /* Emit the function in graphviz format.  */
>  extern void
>  gcc_jit_function_dump_to_dot (gcc_jit_function *func,
> @@ -1518,6 +1595,46 @@ gcc_jit_version_minor (void);
>  extern int
>  gcc_jit_version_patchlevel (void);
>  
> +#define LIBGCCJIT_HAVE_gcc_jit_function_reflection
> +
> +/* Reflection functions to get the number of parameters, return type of
> +   a function and whether a type is a bool from the C API.
> +
> +   This API entrypoint was added in LIBGCCJIT_ABI_15; you can test for its
> +   presence using
> +     #ifdef LIBGCCJIT_HAVE_gcc_jit_function_reflection
> +*/
> +extern gcc_jit_type *
> +gcc_jit_function_get_return_type (gcc_jit_function *func);
> +extern ssize_t
> +gcc_jit_function_get_param_count (gcc_jit_function *func);
> +extern gcc_jit_type *
> +gcc_jit_type_is_array (gcc_jit_type *type);
> +extern int
> +gcc_jit_type_is_bool (gcc_jit_type *type);
> +extern gcc_jit_function_type *
> +gcc_jit_type_is_function_ptr_type (gcc_jit_type *type);
> +extern gcc_jit_type *
> +gcc_jit_function_type_get_return_type (gcc_jit_function_type *function_type);
> +extern ssize_t
> +gcc_jit_function_type_get_param_count (gcc_jit_function_type *function_type);
> +extern gcc_jit_type *
> +gcc_jit_function_type_get_param_type (gcc_jit_function_type *function_type, int index);

Exceeds 80 characters

> +extern int
> +gcc_jit_type_is_int (gcc_jit_type *type);
> +extern gcc_jit_type *
> +gcc_jit_type_is_pointer (gcc_jit_type *type);
> +extern gcc_jit_vector_type *
> +gcc_jit_type_is_vector (gcc_jit_type *type);
> +extern gcc_jit_struct *
> +gcc_jit_type_is_struct (gcc_jit_type *type);
> +extern ssize_t
> +gcc_jit_vector_type_get_num_units (gcc_jit_vector_type *vector_type);
> +extern gcc_jit_type *
> +gcc_jit_vector_type_get_element_type (gcc_jit_vector_type *vector_type);
> +extern gcc_jit_type *
> +gcc_jit_type_unqualified (gcc_jit_type *type);

Apologies for the nit picking :)

  Andrea

^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re: [PATCH] libgccjit: add some reflection functions in the jit C api
  2020-10-15 16:23       ` Andrea Corallo
@ 2020-10-15 17:39         ` Antoni Boucher
  2020-10-15 18:04           ` Andrea Corallo
  2020-10-15 21:52           ` David Malcolm
  0 siblings, 2 replies; 35+ messages in thread
From: Antoni Boucher @ 2020-10-15 17:39 UTC (permalink / raw)
  To: Andrea Corallo; +Cc: Antoni Boucher via Jit, David Malcolm, gcc-patches

[-- Attachment #1: Type: text/plain, Size: 24995 bytes --]

Thanks. I updated the patch with these changes.

Is there any tool to automatically check the style?

On Thu, Oct 15, 2020 at 06:23:18PM +0200, Andrea Corallo wrote:
>Antoni Boucher via Jit <jit@gcc.gnu.org> writes:
>
>Hi Antoni,
>
>Just had a quick look, please find some quite minor comments in line.
>
>> From b0edc9eb8e8d3ba9e1c6a8d061a8627c0b0cf102 Mon Sep 17 00:00:00 2001
>> From: Antoni Boucher <bouanto@zoho.com>
>> Date: Sat, 1 Aug 2020 17:52:17 -0400
>> Subject: [PATCH] This patch add some reflection functions in the jit C api
>>  [PR96889]
>>
>> 2020-09-1  Antoni Boucher  <bouanto@zoho.com>
>>
>>     gcc/jit/
>>             PR target/96889
>>             * docs/topics/compatibility.rst (LIBGCCJIT_ABI_14): New ABI tag.
>>             * docs/topics/functions.rst: Add documentation for the
>>             functions gcc_jit_function_get_return_type and
>>             gcc_jit_function_get_param_count
>>             * libgccjit.c: New functions:
>>               * gcc_jit_function_get_return_type;
>>               * gcc_jit_function_get_param_count;
>>               * gcc_jit_function_type_get_return_type;
>>               * gcc_jit_function_type_get_param_count;
>>               * gcc_jit_function_type_get_param_type;
>>               * gcc_jit_type_unqualified;
>>               * gcc_jit_type_is_array;
>>               * gcc_jit_type_is_bool;
>>               * gcc_jit_type_is_function_ptr_type;
>>               * gcc_jit_type_is_int;
>>               * gcc_jit_type_is_pointer;
>>               * gcc_jit_type_is_vector;
>>               * gcc_jit_vector_type_get_element_type;
>>               * gcc_jit_vector_type_get_num_units;
>>               * gcc_jit_struct_get_field;
>>               * gcc_jit_type_is_struct;
>>               * gcc_jit_struct_get_field_count;
>>             * libgccjit.h
>>             * jit-recording.h: New functions (is_struct and is_vector)
>>             * libgccjit.map (LIBGCCJIT_ABI_14): New ABI tag.
>>
>>     gcc/testsuite/
>>             PR target/96889
>>             * jit.dg/all-non-failing-tests.h: Add test-reflection.c.
>>             * jit.dg/test-reflection.c: New test.
>> ---
>>  gcc/jit/docs/topics/compatibility.rst        |  41 +++
>>  gcc/jit/docs/topics/functions.rst            |  10 +
>>  gcc/jit/jit-recording.h                      |  16 ++
>>  gcc/jit/libgccjit.c                          | 254 +++++++++++++++++++
>>  gcc/jit/libgccjit.h                          | 117 +++++++++
>>  gcc/jit/libgccjit.map                        |  21 ++
>>  gcc/testsuite/jit.dg/all-non-failing-tests.h |  10 +
>>  gcc/testsuite/jit.dg/test-reflection.c       |  89 +++++++
>>  8 files changed, 558 insertions(+)
>>  create mode 100644 gcc/testsuite/jit.dg/test-reflection.c
>>
>> diff --git a/gcc/jit/docs/topics/compatibility.rst b/gcc/jit/docs/topics/compatibility.rst
>> index 6bfa101ed71..16f24d20a75 100644
>> --- a/gcc/jit/docs/topics/compatibility.rst
>> +++ b/gcc/jit/docs/topics/compatibility.rst
>> @@ -226,3 +226,44 @@ entrypoints:
>>  --------------------
>>  ``LIBGCCJIT_ABI_14`` covers the addition of
>>  :func:`gcc_jit_global_set_initializer`
>> +
>> +.. _LIBGCCJIT_ABI_15:
>> +
>> +``LIBGCCJIT_ABI_15``
>> +--------------------
>> +``LIBGCCJIT_ABI_15`` covers the addition of reflection functions via API
>> +entrypoints:
>> +
>> +  * :func:`gcc_jit_function_get_return_type`
>> +
>> +  * :func:`gcc_jit_function_get_param_count`
>> +
>> +  * :func:`gcc_jit_type_is_array`
>> +
>> +  * :func:`gcc_jit_type_is_bool`
>> +
>> +  * :func:`gcc_jit_type_is_int`
>> +
>> +  * :func:`gcc_jit_type_is_pointer`
>> +
>> +  * :func:`gcc_jit_type_is_struct`
>> +
>> +  * :func:`gcc_jit_type_is_vector`
>> +
>> +  * :func:`gcc_jit_type_unqualified`
>> +
>> +  * :func:`gcc_jit_type_is_function_ptr_type`
>> +
>> +  * :func:`gcc_jit_function_type_get_return_type`
>> +
>> +  * :func:`gcc_jit_function_type_get_param_count`
>> +
>> +  * :func:`gcc_jit_function_type_get_param_type`
>> +
>> +  * :func:`gcc_jit_vector_type_get_num_units`
>> +
>> +  * :func:`gcc_jit_vector_type_get_element_type`
>> +
>> +  * :func:`gcc_jit_struct_get_field`
>> +
>> +  * :func:`gcc_jit_struct_get_field_count`
>> diff --git a/gcc/jit/docs/topics/functions.rst b/gcc/jit/docs/topics/functions.rst
>> index eb40d64010e..9819c28cda2 100644
>> --- a/gcc/jit/docs/topics/functions.rst
>> +++ b/gcc/jit/docs/topics/functions.rst
>> @@ -171,6 +171,16 @@ Functions
>>     underlying string, so it is valid to pass in a pointer to an on-stack
>>     buffer.
>>
>> +.. function::  size_t \
>> +               gcc_jit_function_get_param_count (gcc_jit_function *func)
>> +
>> +   Get the number of parameters of the function.
>> +
>> +.. function::  gcc_jit_type \*
>> +               gcc_jit_function_get_return_type (gcc_jit_function *func)
>> +
>> +   Get the return type of the function.
>> +
>>  Blocks
>>  ------
>>  .. type:: gcc_jit_block
>> diff --git a/gcc/jit/jit-recording.h b/gcc/jit/jit-recording.h
>> index 30e37aff387..525b8bc921d 100644
>> --- a/gcc/jit/jit-recording.h
>> +++ b/gcc/jit/jit-recording.h
>> @@ -538,7 +538,9 @@ public:
>>    virtual bool is_bool () const = 0;
>>    virtual type *is_pointer () = 0;
>>    virtual type *is_array () = 0;
>> +  virtual struct_ *is_struct () { return NULL; }
>>    virtual bool is_void () const { return false; }
>> +  virtual vector_type *is_vector () { return NULL; }
>>    virtual bool has_known_size () const { return true; }
>>
>>    bool is_numeric () const
>> @@ -595,6 +597,8 @@ public:
>>    bool is_bool () const FINAL OVERRIDE;
>>    type *is_pointer () FINAL OVERRIDE { return dereference (); }
>>    type *is_array () FINAL OVERRIDE { return NULL; }
>> +  vector_type *is_vector () FINAL OVERRIDE { return NULL; }
>> +  struct_ *is_struct () FINAL OVERRIDE { return NULL; }
>>    bool is_void () const FINAL OVERRIDE { return m_kind == GCC_JIT_TYPE_VOID; }
>>
>>  public:
>> @@ -629,6 +633,8 @@ public:
>>    bool is_bool () const FINAL OVERRIDE { return false; }
>>    type *is_pointer () FINAL OVERRIDE { return m_other_type; }
>>    type *is_array () FINAL OVERRIDE { return NULL; }
>> +  vector_type *is_vector () FINAL OVERRIDE { return NULL; }
>> +  struct_ *is_struct () FINAL OVERRIDE { return NULL; }
>>
>>  private:
>>    string * make_debug_string () FINAL OVERRIDE;
>> @@ -655,6 +661,7 @@ public:
>>    bool is_bool () const FINAL OVERRIDE { return m_other_type->is_bool (); }
>>    type *is_pointer () FINAL OVERRIDE { return m_other_type->is_pointer (); }
>>    type *is_array () FINAL OVERRIDE { return m_other_type->is_array (); }
>> +  struct_ *is_struct () FINAL OVERRIDE { return m_other_type->is_struct (); }
>>
>>  protected:
>>    type *m_other_type;
>> @@ -737,6 +744,8 @@ public:
>>
>>    void replay_into (replayer *) FINAL OVERRIDE;
>>
>> +  vector_type *is_vector () FINAL OVERRIDE { return this; }
>> +
>>  private:
>>    string * make_debug_string () FINAL OVERRIDE;
>>    void write_reproducer (reproducer &r) FINAL OVERRIDE;
>> @@ -765,6 +774,8 @@ class array_type : public type
>>    bool is_bool () const FINAL OVERRIDE { return false; }
>>    type *is_pointer () FINAL OVERRIDE { return NULL; }
>>    type *is_array () FINAL OVERRIDE { return m_element_type; }
>> +  vector_type *is_vector () FINAL OVERRIDE { return NULL; }
>> +  struct_ *is_struct () FINAL OVERRIDE { return NULL; }
>>    int num_elements () { return m_num_elements; }
>>
>>    void replay_into (replayer *) FINAL OVERRIDE;
>> @@ -799,6 +810,8 @@ public:
>>    bool is_bool () const FINAL OVERRIDE { return false; }
>>    type *is_pointer () FINAL OVERRIDE { return NULL; }
>>    type *is_array () FINAL OVERRIDE { return NULL; }
>> +  vector_type *is_vector () FINAL OVERRIDE { return NULL; }
>> +  struct_ *is_struct () FINAL OVERRIDE { return NULL; }
>>
>>    void replay_into (replayer *) FINAL OVERRIDE;
>>
>> @@ -912,6 +925,7 @@ public:
>>    bool is_bool () const FINAL OVERRIDE { return false; }
>>    type *is_pointer () FINAL OVERRIDE { return NULL; }
>>    type *is_array () FINAL OVERRIDE { return NULL; }
>> +  vector_type *is_vector () FINAL OVERRIDE { return NULL; }
>>
>>    bool has_known_size () const FINAL OVERRIDE { return m_fields != NULL; }
>>
>> @@ -943,6 +957,8 @@ public:
>>
>>    const char *access_as_type (reproducer &r) FINAL OVERRIDE;
>>
>> +  struct_ *is_struct () FINAL OVERRIDE { return this; }
>> +
>>  private:
>>    string * make_debug_string () FINAL OVERRIDE;
>>    void write_reproducer (reproducer &r) FINAL OVERRIDE;
>> diff --git a/gcc/jit/libgccjit.c b/gcc/jit/libgccjit.c
>> index a00aefc7108..94a0f1955ec 100644
>> --- a/gcc/jit/libgccjit.c
>> +++ b/gcc/jit/libgccjit.c
>> @@ -21,6 +21,7 @@ along with GCC; see the file COPYING3.  If not see
>>  #include "config.h"
>>  #include "system.h"
>>  #include "coretypes.h"
>> +#include "tm.h"
>>  #include "timevar.h"
>>  #include "typed-splay-tree.h"
>>  #include "cppbuiltin.h"
>> @@ -60,6 +61,14 @@ struct gcc_jit_struct : public gcc::jit::recording::struct_
>>  {
>>  };
>>
>> +struct gcc_jit_function_type : public gcc::jit::recording::function_type
>> +{
>> +};
>> +
>> +struct gcc_jit_vector_type : public gcc::jit::recording::vector_type
>> +{
>> +};
>> +
>>  struct gcc_jit_field : public gcc::jit::recording::field
>>  {
>>  };
>> @@ -510,6 +519,195 @@ gcc_jit_type_get_volatile (gcc_jit_type *type)
>>    return (gcc_jit_type *)type->get_volatile ();
>>  }
>>
>> +/* Public entrypoint.  See description in libgccjit.h.
>> +
>> +   After error-checking, the real work is done by the
>> +   gcc::jit::recording::type::is_array method, in
>> +   jit-recording.c.  */
>> +
>> +gcc_jit_type *
>> +gcc_jit_type_is_array (gcc_jit_type *type)
>> +{
>> +  RETURN_NULL_IF_FAIL (type, NULL, NULL, "NULL type");
>> +
>> +  return (gcc_jit_type *)type->is_array ();
>> +}
>> +
>> +/* Public entrypoint.  See description in libgccjit.h.
>> +
>> +   After error-checking, the real work is done by the
>> +   gcc::jit::recording::type::is_bool method, in
>> +   jit-recording.c.  */
>> +
>> +int
>> +gcc_jit_type_is_bool (gcc_jit_type *type)
>> +{
>> +  RETURN_VAL_IF_FAIL (type, FALSE, NULL, NULL, "NULL type");
>> +
>> +  return type->is_bool ();
>> +}
>> +
>> +/* Public entrypoint.  See description in libgccjit.h.
>> +
>> +   After error-checking, the real work is done by the
>> +   gcc::jit::recording::type::is_pointer method, in
>> +   jit-recording.c.  */
>> +
>> +gcc_jit_type *
>> +gcc_jit_type_is_pointer (gcc_jit_type *type)
>> +{
>> +  RETURN_NULL_IF_FAIL (type, NULL, NULL, "NULL type");
>> +
>> +  return (gcc_jit_type *)type->is_pointer ();
>> +}
>> +
>> +/* Public entrypoint.  See description in libgccjit.h.
>> +
>> +   After error-checking, the real work is done by the
>> +   gcc::jit::recording::type::is_int method, in
>> +   jit-recording.c.  */
>> +
>> +int
>> +gcc_jit_type_is_int (gcc_jit_type *type)
>> +{
>> +  RETURN_VAL_IF_FAIL (type, FALSE, NULL, NULL, "NULL type");
>> +
>> +  return type->is_int ();
>> +}
>> +
>> +/* Public entrypoint.  See description in libgccjit.h.
>> +
>> +   After error-checking, the real work is done by the
>> +   gcc::jit::recording::type::is_vector method, in
>> +   jit-recording.c.  */
>> +
>> +gcc_jit_vector_type *
>> +gcc_jit_type_is_vector (gcc_jit_type *type)
>> +{
>> +  RETURN_NULL_IF_FAIL (type, NULL, NULL, "NULL type");
>> +  gcc::jit::recording::vector_type *vector_type = type->is_vector();
>                                                                   ^^^
>                                                                 space here
>> +  return (gcc_jit_vector_type *)vector_type;
>> +}
>> +
>> +/* Public entrypoint.  See description in libgccjit.h.
>> +
>> +   After error-checking, the real work is done by the
>> +   gcc::jit::recording::type::is_struct method, in
>> +   jit-recording.c.  */
>> +
>> +gcc_jit_struct *
>> +gcc_jit_type_is_struct (gcc_jit_type *type)
>> +{
>> +  RETURN_NULL_IF_FAIL (type, NULL, NULL, "NULL type");
>> +  gcc::jit::recording::struct_ *struct_type = type->is_struct();
>
>Likewise
>
>> +  return (gcc_jit_struct *)struct_type;
>> +}
>> +
>> +/* Public entrypoint.  See description in libgccjit.h.
>> +
>> +   After error-checking, the real work is done by the
>> +   gcc::jit::recording::vector_type::get_num_units method, in
>> +   jit-recording.c.  */
>> +
>> +ssize_t
>> +gcc_jit_vector_type_get_num_units (gcc_jit_vector_type *vector_type)
>> +{
>> +  RETURN_VAL_IF_FAIL (vector_type, -1, NULL, NULL, "NULL vector_type");
>> +  return vector_type->get_num_units ();
>> +}
>> +
>> +/* Public entrypoint.  See description in libgccjit.h.
>> +
>> +   After error-checking, the real work is done by the
>> +   gcc::jit::recording::vector_type::get_element_type method, in
>> +   jit-recording.c.  */
>> +
>> +gcc_jit_type *
>> +gcc_jit_vector_type_get_element_type (gcc_jit_vector_type *vector_type)
>> +{
>> +  RETURN_NULL_IF_FAIL (vector_type, NULL, NULL, "NULL vector_type");
>> +  return (gcc_jit_type *)vector_type->get_element_type ();
>> +}
>> +
>> +/* Public entrypoint.  See description in libgccjit.h.
>> +
>> +   After error-checking, the real work is done by the
>> +   gcc::jit::recording::type::unqualified method, in
>> +   jit-recording.c.  */
>> +
>> +gcc_jit_type *
>> +gcc_jit_type_unqualified (gcc_jit_type *type)
>> +{
>> +  RETURN_NULL_IF_FAIL (type, NULL, NULL, "NULL type");
>> +
>> +  return (gcc_jit_type *)type->unqualified ();
>> +}
>> +
>> +/* Public entrypoint.  See description in libgccjit.h.
>> +
>> +   After error-checking, the real work is done by the
>> +   gcc::jit::recording::type::dyn_cast_function_type method, in
>> +   jit-recording.c.  */
>> +
>> +gcc_jit_function_type *
>> +gcc_jit_type_is_function_ptr_type (gcc_jit_type *type)
>> +{
>> +  RETURN_NULL_IF_FAIL (type, NULL, NULL, "NULL type");
>> +  gcc::jit::recording::type *func_ptr_type = type->dereference ();
>> +  RETURN_NULL_IF_FAIL (func_ptr_type, NULL, NULL, "NULL type");
>> +  gcc::jit::recording::function_type *func_type = func_ptr_type->dyn_cast_function_type();
>
>Likewise (also exceeded 80 characters).
>
>> +  RETURN_NULL_IF_FAIL (func_type, NULL, NULL, "NULL type");
>> +
>> +  return (gcc_jit_function_type *)func_type;
>> +}
>> +
>> +/* Public entrypoint.  See description in libgccjit.h.
>> +
>> +   After error-checking, the real work is done by the
>> +   gcc::jit::recording::function_type::get_return_type method, in
>> +   jit-recording.c.  */
>> +
>> +gcc_jit_type *
>> +gcc_jit_function_type_get_return_type (gcc_jit_function_type *function_type)
>> +{
>> +  RETURN_NULL_IF_FAIL (function_type, NULL, NULL, "NULL struct_type");
>> +  return (gcc_jit_type *)function_type->get_return_type ();
>> +}
>> +
>> +/* Public entrypoint.  See description in libgccjit.h.
>> +
>> +   After error-checking, the real work is done by the
>> +   gcc::jit::recording::function_type::get_param_types method, in
>> +   jit-recording.c.  */
>> +
>> +ssize_t
>> +gcc_jit_function_type_get_param_count (gcc_jit_function_type *function_type)
>> +{
>> +  RETURN_VAL_IF_FAIL (function_type, -1, NULL, NULL, "NULL struct_type");
>> +  return function_type->get_param_types ().length();
>
>Likewise
>
>> +}
>> +
>> +/* Public entrypoint.  See description in libgccjit.h.
>> +
>> +   After error-checking, the real work is done by the
>> +   gcc::jit::recording::function_type::get_param_types method, in
>> +   jit-recording.c.  */
>> +
>> +gcc_jit_type *
>> +gcc_jit_function_type_get_param_type (gcc_jit_function_type *function_type, int index)
>
>Excedes 80 characters
>
>> +{
>> +  RETURN_NULL_IF_FAIL (function_type, NULL, NULL, "NULL struct_type");
>> +  int num_params = function_type->get_param_types ().length ();
>> +  gcc::jit::recording::context *ctxt = function_type->m_ctxt;
>> +  RETURN_NULL_IF_FAIL_PRINTF3 (index < num_params,
>> +			       ctxt, NULL,
>> +			       "index of %d is too large (%s has %d params)",
>> +			       index,
>> +			       function_type->get_debug_string (),
>> +			       num_params);
>> +  return (gcc_jit_type *)function_type->get_param_types ()[index];
>> +}
>> +
>>  /* Public entrypoint.  See description in libgccjit.h.
>>
>>     After error-checking, the real work is done by the
>> @@ -731,6 +929,33 @@ gcc_jit_struct_set_fields (gcc_jit_struct *struct_type,
>>  			   (gcc::jit::recording::field **)fields);
>>  }
>>
>> +
>> +/* Public entrypoint.  See description in libgccjit.h.
>> +
>> +   After error-checking, the real work is done by the
>> +   gcc::jit::recording::fields::get_field method in
>> +   jit-recording.c.  */
>> +extern gcc_jit_field *
>> +gcc_jit_struct_get_field (gcc_jit_struct *struct_type,
>> +			   int index)
>> +{
>> +  RETURN_NULL_IF_FAIL (struct_type, NULL, NULL, "NULL struct type");
>> +  return (gcc_jit_field *)struct_type->get_fields()->get_field(index);
>
>Space before (
>
>> +}
>> +
>> +/* Public entrypoint.  See description in libgccjit.h.
>> +
>> +   After error-checking, this calls the trivial
>> +   gcc::jit::recording::struct_::get_fields method in
>> +   jit-recording.h.  */
>> +
>> +ssize_t
>> +gcc_jit_struct_get_field_count (gcc_jit_struct *struct_type)
>> +{
>> +  RETURN_VAL_IF_FAIL (struct_type, -1, NULL, NULL, "NULL struct type");
>> +  return struct_type->get_fields()->length();
>
>Likewise
>
>> +}
>> +
>>  /* Public entrypoint.  See description in libgccjit.h.
>>
>>     After error-checking, the real work is done by the
>> @@ -1012,6 +1237,35 @@ gcc_jit_function_get_param (gcc_jit_function *func, int index)
>>    return static_cast <gcc_jit_param *> (func->get_param (index));
>>  }
>>
>> +/* Public entrypoint.  See description in libgccjit.h.
>> +
>> +   After error-checking, the real work is done by the
>> +   gcc::jit::recording::function::get_params method, in
>> +   jit-recording.h.
>> +  */
>> +
>> +ssize_t
>> +gcc_jit_function_get_param_count (gcc_jit_function *func)
>> +{
>> +  RETURN_VAL_IF_FAIL (func, -1, NULL, NULL, "NULL function");
>> +  gcc::jit::recording::context *ctxt = func->m_ctxt;
>> +  JIT_LOG_FUNC (ctxt->get_logger ());
>> +  return func->get_params ().length ();
>> +}
>> +
>> +/* Public entrypoint.  See description in libgccjit.h.
>> +
>> +   After error-checking, the real work is done by the
>> +   gcc::jit::recording::function::get_return_type method, in
>> +   jit-recording.h.  */
>> +
>> +gcc_jit_type *
>> +gcc_jit_function_get_return_type (gcc_jit_function *func)
>> +{
>> +    RETURN_NULL_IF_FAIL (func, NULL, NULL, "NULL function");
>> +    return (gcc_jit_type *)func->get_return_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 7134841bb07..b0a3d941e9c 100644
>> --- a/gcc/jit/libgccjit.h
>> +++ b/gcc/jit/libgccjit.h
>> @@ -96,6 +96,12 @@ typedef struct gcc_jit_field gcc_jit_field;
>>     the layout for, or an opaque type.  */
>>  typedef struct gcc_jit_struct gcc_jit_struct;
>>
>> +/* A gcc_jit_function_type encapsulates a function type.  */
>> +typedef struct gcc_jit_function_type gcc_jit_function_type;
>> +
>> +/* A gcc_jit_vector_type encapsulates a vector type.  */
>> +typedef struct gcc_jit_vector_type gcc_jit_vector_type;
>> +
>>  /* A gcc_jit_function encapsulates a function: either one that you're
>>     creating yourself, or a reference to one that you're dynamically
>>     linking to within the rest of the process.  */
>> @@ -586,6 +592,60 @@ gcc_jit_type_get_const (gcc_jit_type *type);
>>  extern gcc_jit_type *
>>  gcc_jit_type_get_volatile (gcc_jit_type *type);
>>
>> +/* Given type "T", return TRUE if the type is an array.  */
>> +extern gcc_jit_type *
>> +gcc_jit_type_is_array (gcc_jit_type *type);
>> +
>> +/* Given type "T", return TRUE if the type is a bool.  */
>> +extern int
>> +gcc_jit_type_is_bool (gcc_jit_type *type);
>> +
>> +/* Given type "T", return the function type if it is one.  */
>> +extern gcc_jit_function_type *
>> +gcc_jit_type_is_function_ptr_type (gcc_jit_type *type);
>> +
>> +/* Given a function type, return its return type. */
>
>GNU stile wants dot + 2 spaces at the end of a comment.
>
>> +extern gcc_jit_type *
>> +gcc_jit_function_type_get_return_type (gcc_jit_function_type *function_type);
>> +
>> +/* Given a function type, return its number of parameters. */
>
>Likewise
>
>> +extern ssize_t
>> +gcc_jit_function_type_get_param_count (gcc_jit_function_type *function_type);
>> +
>> +/* Given a function type, return the type of the specified parameter. */
>
>Likewise
>
>> +extern gcc_jit_type *
>> +gcc_jit_function_type_get_param_type (gcc_jit_function_type *function_type, int index);
>
>Exceeds 80 characters
>
>> +
>> +/* Given type "T", return the type pointed by the pointer type
>> + * or NULL if it's not a pointer.  */
>> +extern gcc_jit_type *
>> +gcc_jit_type_is_pointer (gcc_jit_type *type);
>> +
>> +/* Given type "T", return TRUE if the type is an int.  */
>> +extern int
>> +gcc_jit_type_is_int (gcc_jit_type *type);
>> +
>> +/* Given type "T", return the unqualified type, i.e. for a
>> + * decorated type, return the type it wraps.  */
>> +extern gcc_jit_type *
>> +gcc_jit_type_unqualified (gcc_jit_type *type);
>> +
>> +/* Given type "T", return TRUE if the type is a vector type.  */
>> +extern gcc_jit_vector_type *
>> +gcc_jit_type_is_vector (gcc_jit_type *type);
>> +
>> +/* Given type "T", return the struct type or NULL.  */
>> +extern gcc_jit_struct *
>> +gcc_jit_type_is_struct (gcc_jit_type *type);
>> +
>> +/* Given a vector type, return the number of units it contains. */
>
>One space more before */
>
>> +extern ssize_t
>> +gcc_jit_vector_type_get_num_units (gcc_jit_vector_type *vector_type);
>> +
>> +/* Given a vector type, return the type of its elements. */
>
>Likewise
>
>> +extern gcc_jit_type *
>> +gcc_jit_vector_type_get_element_type (gcc_jit_vector_type *vector_type);
>> +
>>  /* Given type "T", get type "T[N]" (for a constant N).  */
>>  extern gcc_jit_type *
>>  gcc_jit_context_new_array_type (gcc_jit_context *ctxt,
>> @@ -647,6 +707,15 @@ gcc_jit_struct_set_fields (gcc_jit_struct *struct_type,
>>  			   int num_fields,
>>  			   gcc_jit_field **fields);
>>
>> +/* Get a field by index. */
>
>Likewise
>
>> +extern gcc_jit_field *
>> +gcc_jit_struct_get_field (gcc_jit_struct *struct_type,
>> +			   int index);
>> +
>> +/* Get the number of fields. */
>
>Likewise
>
>> +extern ssize_t
>> +gcc_jit_struct_get_field_count (gcc_jit_struct *struct_type);
>> +
>>  /* Unions work similarly to structs.  */
>>  extern gcc_jit_type *
>>  gcc_jit_context_new_union_type (gcc_jit_context *ctxt,
>> @@ -740,6 +809,14 @@ gcc_jit_function_as_object (gcc_jit_function *func);
>>  extern gcc_jit_param *
>>  gcc_jit_function_get_param (gcc_jit_function *func, int index);
>>
>> +/* Get the number of params of a function.  */
>> +extern ssize_t
>> +gcc_jit_function_get_param_count (gcc_jit_function *func);
>> +
>> +/* Get the return type of a function.  */
>> +extern gcc_jit_type *
>> +gcc_jit_function_get_return_type (gcc_jit_function *func);
>> +
>>  /* Emit the function in graphviz format.  */
>>  extern void
>>  gcc_jit_function_dump_to_dot (gcc_jit_function *func,
>> @@ -1518,6 +1595,46 @@ gcc_jit_version_minor (void);
>>  extern int
>>  gcc_jit_version_patchlevel (void);
>>
>> +#define LIBGCCJIT_HAVE_gcc_jit_function_reflection
>> +
>> +/* Reflection functions to get the number of parameters, return type of
>> +   a function and whether a type is a bool from the C API.
>> +
>> +   This API entrypoint was added in LIBGCCJIT_ABI_15; you can test for its
>> +   presence using
>> +     #ifdef LIBGCCJIT_HAVE_gcc_jit_function_reflection
>> +*/
>> +extern gcc_jit_type *
>> +gcc_jit_function_get_return_type (gcc_jit_function *func);
>> +extern ssize_t
>> +gcc_jit_function_get_param_count (gcc_jit_function *func);
>> +extern gcc_jit_type *
>> +gcc_jit_type_is_array (gcc_jit_type *type);
>> +extern int
>> +gcc_jit_type_is_bool (gcc_jit_type *type);
>> +extern gcc_jit_function_type *
>> +gcc_jit_type_is_function_ptr_type (gcc_jit_type *type);
>> +extern gcc_jit_type *
>> +gcc_jit_function_type_get_return_type (gcc_jit_function_type *function_type);
>> +extern ssize_t
>> +gcc_jit_function_type_get_param_count (gcc_jit_function_type *function_type);
>> +extern gcc_jit_type *
>> +gcc_jit_function_type_get_param_type (gcc_jit_function_type *function_type, int index);
>
>Exceeds 80 characters
>
>> +extern int
>> +gcc_jit_type_is_int (gcc_jit_type *type);
>> +extern gcc_jit_type *
>> +gcc_jit_type_is_pointer (gcc_jit_type *type);
>> +extern gcc_jit_vector_type *
>> +gcc_jit_type_is_vector (gcc_jit_type *type);
>> +extern gcc_jit_struct *
>> +gcc_jit_type_is_struct (gcc_jit_type *type);
>> +extern ssize_t
>> +gcc_jit_vector_type_get_num_units (gcc_jit_vector_type *vector_type);
>> +extern gcc_jit_type *
>> +gcc_jit_vector_type_get_element_type (gcc_jit_vector_type *vector_type);
>> +extern gcc_jit_type *
>> +gcc_jit_type_unqualified (gcc_jit_type *type);
>
>Apologies for the nit picking :)
>
>  Andrea

[-- Attachment #2: 0001-This-patch-add-some-reflection-functions-in-the-jit-.patch --]
[-- Type: text/plain, Size: 28130 bytes --]

From 21fff4bdad3691f7ad5a77735062ce96701db511 Mon Sep 17 00:00:00 2001
From: Antoni Boucher <bouanto@zoho.com>
Date: Sat, 1 Aug 2020 17:52:17 -0400
Subject: [PATCH] This patch add some reflection functions in the jit C api
 [PR96889]

2020-09-1  Antoni Boucher  <bouanto@zoho.com>

    gcc/jit/
            PR target/96889
            * docs/topics/compatibility.rst (LIBGCCJIT_ABI_14): New ABI tag.
            * docs/topics/functions.rst: Add documentation for the
            functions gcc_jit_function_get_return_type and
            gcc_jit_function_get_param_count
            * libgccjit.c: New functions:
              * gcc_jit_function_get_return_type;
              * gcc_jit_function_get_param_count;
              * gcc_jit_function_type_get_return_type;
              * gcc_jit_function_type_get_param_count;
              * gcc_jit_function_type_get_param_type;
              * gcc_jit_type_unqualified;
              * gcc_jit_type_is_array;
              * gcc_jit_type_is_bool;
              * gcc_jit_type_is_function_ptr_type;
              * gcc_jit_type_is_int;
              * gcc_jit_type_is_pointer;
              * gcc_jit_type_is_vector;
              * gcc_jit_vector_type_get_element_type;
              * gcc_jit_vector_type_get_num_units;
              * gcc_jit_struct_get_field;
              * gcc_jit_type_is_struct;
              * gcc_jit_struct_get_field_count;
            * libgccjit.h
            * jit-recording.h: New functions (is_struct and is_vector)
            * libgccjit.map (LIBGCCJIT_ABI_14): New ABI tag.

    gcc/testsuite/
            PR target/96889
            * jit.dg/all-non-failing-tests.h: Add test-reflection.c.
            * jit.dg/test-reflection.c: New test.
---
 gcc/jit/docs/topics/compatibility.rst        |  41 +++
 gcc/jit/docs/topics/functions.rst            |  10 +
 gcc/jit/jit-recording.h                      |  16 ++
 gcc/jit/libgccjit.c                          | 256 +++++++++++++++++++
 gcc/jit/libgccjit.h                          | 119 +++++++++
 gcc/jit/libgccjit.map                        |  21 ++
 gcc/testsuite/jit.dg/all-non-failing-tests.h |  10 +
 gcc/testsuite/jit.dg/test-reflection.c       |  89 +++++++
 8 files changed, 562 insertions(+)
 create mode 100644 gcc/testsuite/jit.dg/test-reflection.c

diff --git a/gcc/jit/docs/topics/compatibility.rst b/gcc/jit/docs/topics/compatibility.rst
index 6bfa101ed71..16f24d20a75 100644
--- a/gcc/jit/docs/topics/compatibility.rst
+++ b/gcc/jit/docs/topics/compatibility.rst
@@ -226,3 +226,44 @@ entrypoints:
 --------------------
 ``LIBGCCJIT_ABI_14`` covers the addition of
 :func:`gcc_jit_global_set_initializer`
+
+.. _LIBGCCJIT_ABI_15:
+
+``LIBGCCJIT_ABI_15``
+--------------------
+``LIBGCCJIT_ABI_15`` covers the addition of reflection functions via API
+entrypoints:
+
+  * :func:`gcc_jit_function_get_return_type`
+
+  * :func:`gcc_jit_function_get_param_count`
+
+  * :func:`gcc_jit_type_is_array`
+
+  * :func:`gcc_jit_type_is_bool`
+
+  * :func:`gcc_jit_type_is_int`
+
+  * :func:`gcc_jit_type_is_pointer`
+
+  * :func:`gcc_jit_type_is_struct`
+
+  * :func:`gcc_jit_type_is_vector`
+
+  * :func:`gcc_jit_type_unqualified`
+
+  * :func:`gcc_jit_type_is_function_ptr_type`
+
+  * :func:`gcc_jit_function_type_get_return_type`
+
+  * :func:`gcc_jit_function_type_get_param_count`
+
+  * :func:`gcc_jit_function_type_get_param_type`
+
+  * :func:`gcc_jit_vector_type_get_num_units`
+
+  * :func:`gcc_jit_vector_type_get_element_type`
+
+  * :func:`gcc_jit_struct_get_field`
+
+  * :func:`gcc_jit_struct_get_field_count`
diff --git a/gcc/jit/docs/topics/functions.rst b/gcc/jit/docs/topics/functions.rst
index eb40d64010e..9819c28cda2 100644
--- a/gcc/jit/docs/topics/functions.rst
+++ b/gcc/jit/docs/topics/functions.rst
@@ -171,6 +171,16 @@ Functions
    underlying string, so it is valid to pass in a pointer to an on-stack
    buffer.
 
+.. function::  size_t \
+               gcc_jit_function_get_param_count (gcc_jit_function *func)
+
+   Get the number of parameters of the function.
+
+.. function::  gcc_jit_type \*
+               gcc_jit_function_get_return_type (gcc_jit_function *func)
+
+   Get the return type of the function.
+
 Blocks
 ------
 .. type:: gcc_jit_block
diff --git a/gcc/jit/jit-recording.h b/gcc/jit/jit-recording.h
index 30e37aff387..525b8bc921d 100644
--- a/gcc/jit/jit-recording.h
+++ b/gcc/jit/jit-recording.h
@@ -538,7 +538,9 @@ public:
   virtual bool is_bool () const = 0;
   virtual type *is_pointer () = 0;
   virtual type *is_array () = 0;
+  virtual struct_ *is_struct () { return NULL; }
   virtual bool is_void () const { return false; }
+  virtual vector_type *is_vector () { return NULL; }
   virtual bool has_known_size () const { return true; }
 
   bool is_numeric () const
@@ -595,6 +597,8 @@ public:
   bool is_bool () const FINAL OVERRIDE;
   type *is_pointer () FINAL OVERRIDE { return dereference (); }
   type *is_array () FINAL OVERRIDE { return NULL; }
+  vector_type *is_vector () FINAL OVERRIDE { return NULL; }
+  struct_ *is_struct () FINAL OVERRIDE { return NULL; }
   bool is_void () const FINAL OVERRIDE { return m_kind == GCC_JIT_TYPE_VOID; }
 
 public:
@@ -629,6 +633,8 @@ public:
   bool is_bool () const FINAL OVERRIDE { return false; }
   type *is_pointer () FINAL OVERRIDE { return m_other_type; }
   type *is_array () FINAL OVERRIDE { return NULL; }
+  vector_type *is_vector () FINAL OVERRIDE { return NULL; }
+  struct_ *is_struct () FINAL OVERRIDE { return NULL; }
 
 private:
   string * make_debug_string () FINAL OVERRIDE;
@@ -655,6 +661,7 @@ public:
   bool is_bool () const FINAL OVERRIDE { return m_other_type->is_bool (); }
   type *is_pointer () FINAL OVERRIDE { return m_other_type->is_pointer (); }
   type *is_array () FINAL OVERRIDE { return m_other_type->is_array (); }
+  struct_ *is_struct () FINAL OVERRIDE { return m_other_type->is_struct (); }
 
 protected:
   type *m_other_type;
@@ -737,6 +744,8 @@ public:
 
   void replay_into (replayer *) FINAL OVERRIDE;
 
+  vector_type *is_vector () FINAL OVERRIDE { return this; }
+
 private:
   string * make_debug_string () FINAL OVERRIDE;
   void write_reproducer (reproducer &r) FINAL OVERRIDE;
@@ -765,6 +774,8 @@ class array_type : public type
   bool is_bool () const FINAL OVERRIDE { return false; }
   type *is_pointer () FINAL OVERRIDE { return NULL; }
   type *is_array () FINAL OVERRIDE { return m_element_type; }
+  vector_type *is_vector () FINAL OVERRIDE { return NULL; }
+  struct_ *is_struct () FINAL OVERRIDE { return NULL; }
   int num_elements () { return m_num_elements; }
 
   void replay_into (replayer *) FINAL OVERRIDE;
@@ -799,6 +810,8 @@ public:
   bool is_bool () const FINAL OVERRIDE { return false; }
   type *is_pointer () FINAL OVERRIDE { return NULL; }
   type *is_array () FINAL OVERRIDE { return NULL; }
+  vector_type *is_vector () FINAL OVERRIDE { return NULL; }
+  struct_ *is_struct () FINAL OVERRIDE { return NULL; }
 
   void replay_into (replayer *) FINAL OVERRIDE;
 
@@ -912,6 +925,7 @@ public:
   bool is_bool () const FINAL OVERRIDE { return false; }
   type *is_pointer () FINAL OVERRIDE { return NULL; }
   type *is_array () FINAL OVERRIDE { return NULL; }
+  vector_type *is_vector () FINAL OVERRIDE { return NULL; }
 
   bool has_known_size () const FINAL OVERRIDE { return m_fields != NULL; }
 
@@ -943,6 +957,8 @@ public:
 
   const char *access_as_type (reproducer &r) FINAL OVERRIDE;
 
+  struct_ *is_struct () FINAL OVERRIDE { return this; }
+
 private:
   string * make_debug_string () FINAL OVERRIDE;
   void write_reproducer (reproducer &r) FINAL OVERRIDE;
diff --git a/gcc/jit/libgccjit.c b/gcc/jit/libgccjit.c
index a00aefc7108..8e6a9e85ff0 100644
--- a/gcc/jit/libgccjit.c
+++ b/gcc/jit/libgccjit.c
@@ -21,6 +21,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "config.h"
 #include "system.h"
 #include "coretypes.h"
+#include "tm.h"
 #include "timevar.h"
 #include "typed-splay-tree.h"
 #include "cppbuiltin.h"
@@ -60,6 +61,14 @@ struct gcc_jit_struct : public gcc::jit::recording::struct_
 {
 };
 
+struct gcc_jit_function_type : public gcc::jit::recording::function_type
+{
+};
+
+struct gcc_jit_vector_type : public gcc::jit::recording::vector_type
+{
+};
+
 struct gcc_jit_field : public gcc::jit::recording::field
 {
 };
@@ -510,6 +519,197 @@ gcc_jit_type_get_volatile (gcc_jit_type *type)
   return (gcc_jit_type *)type->get_volatile ();
 }
 
+/* Public entrypoint.  See description in libgccjit.h.
+
+   After error-checking, the real work is done by the
+   gcc::jit::recording::type::is_array method, in
+   jit-recording.c.  */
+
+gcc_jit_type *
+gcc_jit_type_is_array (gcc_jit_type *type)
+{
+  RETURN_NULL_IF_FAIL (type, NULL, NULL, "NULL type");
+
+  return (gcc_jit_type *)type->is_array ();
+}
+
+/* Public entrypoint.  See description in libgccjit.h.
+
+   After error-checking, the real work is done by the
+   gcc::jit::recording::type::is_bool method, in
+   jit-recording.c.  */
+
+int
+gcc_jit_type_is_bool (gcc_jit_type *type)
+{
+  RETURN_VAL_IF_FAIL (type, FALSE, NULL, NULL, "NULL type");
+
+  return type->is_bool ();
+}
+
+/* Public entrypoint.  See description in libgccjit.h.
+
+   After error-checking, the real work is done by the
+   gcc::jit::recording::type::is_pointer method, in
+   jit-recording.c.  */
+
+gcc_jit_type *
+gcc_jit_type_is_pointer (gcc_jit_type *type)
+{
+  RETURN_NULL_IF_FAIL (type, NULL, NULL, "NULL type");
+
+  return (gcc_jit_type *)type->is_pointer ();
+}
+
+/* Public entrypoint.  See description in libgccjit.h.
+
+   After error-checking, the real work is done by the
+   gcc::jit::recording::type::is_int method, in
+   jit-recording.c.  */
+
+int
+gcc_jit_type_is_int (gcc_jit_type *type)
+{
+  RETURN_VAL_IF_FAIL (type, FALSE, NULL, NULL, "NULL type");
+
+  return type->is_int ();
+}
+
+/* Public entrypoint.  See description in libgccjit.h.
+
+   After error-checking, the real work is done by the
+   gcc::jit::recording::type::is_vector method, in
+   jit-recording.c.  */
+
+gcc_jit_vector_type *
+gcc_jit_type_is_vector (gcc_jit_type *type)
+{
+  RETURN_NULL_IF_FAIL (type, NULL, NULL, "NULL type");
+  gcc::jit::recording::vector_type *vector_type = type->is_vector ();
+  return (gcc_jit_vector_type *)vector_type;
+}
+
+/* Public entrypoint.  See description in libgccjit.h.
+
+   After error-checking, the real work is done by the
+   gcc::jit::recording::type::is_struct method, in
+   jit-recording.c.  */
+
+gcc_jit_struct *
+gcc_jit_type_is_struct (gcc_jit_type *type)
+{
+  RETURN_NULL_IF_FAIL (type, NULL, NULL, "NULL type");
+  gcc::jit::recording::struct_ *struct_type = type->is_struct ();
+  return (gcc_jit_struct *)struct_type;
+}
+
+/* Public entrypoint.  See description in libgccjit.h.
+
+   After error-checking, the real work is done by the
+   gcc::jit::recording::vector_type::get_num_units method, in
+   jit-recording.c.  */
+
+ssize_t
+gcc_jit_vector_type_get_num_units (gcc_jit_vector_type *vector_type)
+{
+  RETURN_VAL_IF_FAIL (vector_type, -1, NULL, NULL, "NULL vector_type");
+  return vector_type->get_num_units ();
+}
+
+/* Public entrypoint.  See description in libgccjit.h.
+
+   After error-checking, the real work is done by the
+   gcc::jit::recording::vector_type::get_element_type method, in
+   jit-recording.c.  */
+
+gcc_jit_type *
+gcc_jit_vector_type_get_element_type (gcc_jit_vector_type *vector_type)
+{
+  RETURN_NULL_IF_FAIL (vector_type, NULL, NULL, "NULL vector_type");
+  return (gcc_jit_type *)vector_type->get_element_type ();
+}
+
+/* Public entrypoint.  See description in libgccjit.h.
+
+   After error-checking, the real work is done by the
+   gcc::jit::recording::type::unqualified method, in
+   jit-recording.c.  */
+
+gcc_jit_type *
+gcc_jit_type_unqualified (gcc_jit_type *type)
+{
+  RETURN_NULL_IF_FAIL (type, NULL, NULL, "NULL type");
+
+  return (gcc_jit_type *)type->unqualified ();
+}
+
+/* Public entrypoint.  See description in libgccjit.h.
+
+   After error-checking, the real work is done by the
+   gcc::jit::recording::type::dyn_cast_function_type method, in
+   jit-recording.c.  */
+
+gcc_jit_function_type *
+gcc_jit_type_is_function_ptr_type (gcc_jit_type *type)
+{
+  RETURN_NULL_IF_FAIL (type, NULL, NULL, "NULL type");
+  gcc::jit::recording::type *func_ptr_type = type->dereference ();
+  RETURN_NULL_IF_FAIL (func_ptr_type, NULL, NULL, "NULL type");
+  gcc::jit::recording::function_type *func_type =
+    func_ptr_type->dyn_cast_function_type ();
+  RETURN_NULL_IF_FAIL (func_type, NULL, NULL, "NULL type");
+
+  return (gcc_jit_function_type *)func_type;
+}
+
+/* Public entrypoint.  See description in libgccjit.h.
+
+   After error-checking, the real work is done by the
+   gcc::jit::recording::function_type::get_return_type method, in
+   jit-recording.c.  */
+
+gcc_jit_type *
+gcc_jit_function_type_get_return_type (gcc_jit_function_type *function_type)
+{
+  RETURN_NULL_IF_FAIL (function_type, NULL, NULL, "NULL struct_type");
+  return (gcc_jit_type *)function_type->get_return_type ();
+}
+
+/* Public entrypoint.  See description in libgccjit.h.
+
+   After error-checking, the real work is done by the
+   gcc::jit::recording::function_type::get_param_types method, in
+   jit-recording.c.  */
+
+ssize_t
+gcc_jit_function_type_get_param_count (gcc_jit_function_type *function_type)
+{
+  RETURN_VAL_IF_FAIL (function_type, -1, NULL, NULL, "NULL struct_type");
+  return function_type->get_param_types ().length ();
+}
+
+/* Public entrypoint.  See description in libgccjit.h.
+
+   After error-checking, the real work is done by the
+   gcc::jit::recording::function_type::get_param_types method, in
+   jit-recording.c.  */
+
+gcc_jit_type *
+gcc_jit_function_type_get_param_type (gcc_jit_function_type *function_type,
+				int index)
+{
+  RETURN_NULL_IF_FAIL (function_type, NULL, NULL, "NULL struct_type");
+  int num_params = function_type->get_param_types ().length ();
+  gcc::jit::recording::context *ctxt = function_type->m_ctxt;
+  RETURN_NULL_IF_FAIL_PRINTF3 (index < num_params,
+			       ctxt, NULL,
+			       "index of %d is too large (%s has %d params)",
+			       index,
+			       function_type->get_debug_string (),
+			       num_params);
+  return (gcc_jit_type *)function_type->get_param_types ()[index];
+}
+
 /* Public entrypoint.  See description in libgccjit.h.
 
    After error-checking, the real work is done by the
@@ -731,6 +931,33 @@ gcc_jit_struct_set_fields (gcc_jit_struct *struct_type,
 			   (gcc::jit::recording::field **)fields);
 }
 
+
+/* Public entrypoint.  See description in libgccjit.h.
+
+   After error-checking, the real work is done by the
+   gcc::jit::recording::fields::get_field method in
+   jit-recording.c.  */
+extern gcc_jit_field *
+gcc_jit_struct_get_field (gcc_jit_struct *struct_type,
+			   int index)
+{
+  RETURN_NULL_IF_FAIL (struct_type, NULL, NULL, "NULL struct type");
+  return (gcc_jit_field *)struct_type->get_fields ()->get_field (index);
+}
+
+/* Public entrypoint.  See description in libgccjit.h.
+
+   After error-checking, this calls the trivial
+   gcc::jit::recording::struct_::get_fields method in
+   jit-recording.h.  */
+
+ssize_t
+gcc_jit_struct_get_field_count (gcc_jit_struct *struct_type)
+{
+  RETURN_VAL_IF_FAIL (struct_type, -1, NULL, NULL, "NULL struct type");
+  return struct_type->get_fields ()->length ();
+}
+
 /* Public entrypoint.  See description in libgccjit.h.
 
    After error-checking, the real work is done by the
@@ -1012,6 +1239,35 @@ gcc_jit_function_get_param (gcc_jit_function *func, int index)
   return static_cast <gcc_jit_param *> (func->get_param (index));
 }
 
+/* Public entrypoint.  See description in libgccjit.h.
+
+   After error-checking, the real work is done by the
+   gcc::jit::recording::function::get_params method, in
+   jit-recording.h.
+  */
+
+ssize_t
+gcc_jit_function_get_param_count (gcc_jit_function *func)
+{
+  RETURN_VAL_IF_FAIL (func, -1, NULL, NULL, "NULL function");
+  gcc::jit::recording::context *ctxt = func->m_ctxt;
+  JIT_LOG_FUNC (ctxt->get_logger ());
+  return func->get_params ().length ();
+}
+
+/* Public entrypoint.  See description in libgccjit.h.
+
+   After error-checking, the real work is done by the
+   gcc::jit::recording::function::get_return_type method, in
+   jit-recording.h.  */
+
+gcc_jit_type *
+gcc_jit_function_get_return_type (gcc_jit_function *func)
+{
+    RETURN_NULL_IF_FAIL (func, NULL, NULL, "NULL function");
+    return (gcc_jit_type *)func->get_return_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 7134841bb07..6056d00a3ea 100644
--- a/gcc/jit/libgccjit.h
+++ b/gcc/jit/libgccjit.h
@@ -96,6 +96,12 @@ typedef struct gcc_jit_field gcc_jit_field;
    the layout for, or an opaque type.  */
 typedef struct gcc_jit_struct gcc_jit_struct;
 
+/* A gcc_jit_function_type encapsulates a function type.  */
+typedef struct gcc_jit_function_type gcc_jit_function_type;
+
+/* A gcc_jit_vector_type encapsulates a vector type.  */
+typedef struct gcc_jit_vector_type gcc_jit_vector_type;
+
 /* A gcc_jit_function encapsulates a function: either one that you're
    creating yourself, or a reference to one that you're dynamically
    linking to within the rest of the process.  */
@@ -586,6 +592,61 @@ gcc_jit_type_get_const (gcc_jit_type *type);
 extern gcc_jit_type *
 gcc_jit_type_get_volatile (gcc_jit_type *type);
 
+/* Given type "T", return TRUE if the type is an array.  */
+extern gcc_jit_type *
+gcc_jit_type_is_array (gcc_jit_type *type);
+
+/* Given type "T", return TRUE if the type is a bool.  */
+extern int
+gcc_jit_type_is_bool (gcc_jit_type *type);
+
+/* Given type "T", return the function type if it is one.  */
+extern gcc_jit_function_type *
+gcc_jit_type_is_function_ptr_type (gcc_jit_type *type);
+
+/* Given a function type, return its return type.  */
+extern gcc_jit_type *
+gcc_jit_function_type_get_return_type (gcc_jit_function_type *function_type);
+
+/* Given a function type, return its number of parameters.  */
+extern ssize_t
+gcc_jit_function_type_get_param_count (gcc_jit_function_type *function_type);
+
+/* Given a function type, return the type of the specified parameter.  */
+extern gcc_jit_type *
+gcc_jit_function_type_get_param_type (gcc_jit_function_type *function_type,
+				int index);
+
+/* Given type "T", return the type pointed by the pointer type
+ * or NULL if it's not a pointer.  */
+extern gcc_jit_type *
+gcc_jit_type_is_pointer (gcc_jit_type *type);
+
+/* Given type "T", return TRUE if the type is an int.  */
+extern int
+gcc_jit_type_is_int (gcc_jit_type *type);
+
+/* Given type "T", return the unqualified type, i.e. for a
+ * decorated type, return the type it wraps.  */
+extern gcc_jit_type *
+gcc_jit_type_unqualified (gcc_jit_type *type);
+
+/* Given type "T", return TRUE if the type is a vector type.  */
+extern gcc_jit_vector_type *
+gcc_jit_type_is_vector (gcc_jit_type *type);
+
+/* Given type "T", return the struct type or NULL.  */
+extern gcc_jit_struct *
+gcc_jit_type_is_struct (gcc_jit_type *type);
+
+/* Given a vector type, return the number of units it contains.  */
+extern ssize_t
+gcc_jit_vector_type_get_num_units (gcc_jit_vector_type *vector_type);
+
+/* Given a vector type, return the type of its elements.  */
+extern gcc_jit_type *
+gcc_jit_vector_type_get_element_type (gcc_jit_vector_type *vector_type);
+
 /* Given type "T", get type "T[N]" (for a constant N).  */
 extern gcc_jit_type *
 gcc_jit_context_new_array_type (gcc_jit_context *ctxt,
@@ -647,6 +708,15 @@ gcc_jit_struct_set_fields (gcc_jit_struct *struct_type,
 			   int num_fields,
 			   gcc_jit_field **fields);
 
+/* Get a field by index.  */
+extern gcc_jit_field *
+gcc_jit_struct_get_field (gcc_jit_struct *struct_type,
+			   int index);
+
+/* Get the number of fields.  */
+extern ssize_t
+gcc_jit_struct_get_field_count (gcc_jit_struct *struct_type);
+
 /* Unions work similarly to structs.  */
 extern gcc_jit_type *
 gcc_jit_context_new_union_type (gcc_jit_context *ctxt,
@@ -740,6 +810,14 @@ gcc_jit_function_as_object (gcc_jit_function *func);
 extern gcc_jit_param *
 gcc_jit_function_get_param (gcc_jit_function *func, int index);
 
+/* Get the number of params of a function.  */
+extern ssize_t
+gcc_jit_function_get_param_count (gcc_jit_function *func);
+
+/* Get the return type of a function.  */
+extern gcc_jit_type *
+gcc_jit_function_get_return_type (gcc_jit_function *func);
+
 /* Emit the function in graphviz format.  */
 extern void
 gcc_jit_function_dump_to_dot (gcc_jit_function *func,
@@ -1518,6 +1596,47 @@ gcc_jit_version_minor (void);
 extern int
 gcc_jit_version_patchlevel (void);
 
+#define LIBGCCJIT_HAVE_gcc_jit_function_reflection
+
+/* Reflection functions to get the number of parameters, return type of
+   a function and whether a type is a bool from the C API.
+
+   This API entrypoint was added in LIBGCCJIT_ABI_15; you can test for its
+   presence using
+     #ifdef LIBGCCJIT_HAVE_gcc_jit_function_reflection
+*/
+extern gcc_jit_type *
+gcc_jit_function_get_return_type (gcc_jit_function *func);
+extern ssize_t
+gcc_jit_function_get_param_count (gcc_jit_function *func);
+extern gcc_jit_type *
+gcc_jit_type_is_array (gcc_jit_type *type);
+extern int
+gcc_jit_type_is_bool (gcc_jit_type *type);
+extern gcc_jit_function_type *
+gcc_jit_type_is_function_ptr_type (gcc_jit_type *type);
+extern gcc_jit_type *
+gcc_jit_function_type_get_return_type (gcc_jit_function_type *function_type);
+extern ssize_t
+gcc_jit_function_type_get_param_count (gcc_jit_function_type *function_type);
+extern gcc_jit_type *
+gcc_jit_function_type_get_param_type (gcc_jit_function_type *function_type,
+				int index);
+extern int
+gcc_jit_type_is_int (gcc_jit_type *type);
+extern gcc_jit_type *
+gcc_jit_type_is_pointer (gcc_jit_type *type);
+extern gcc_jit_vector_type *
+gcc_jit_type_is_vector (gcc_jit_type *type);
+extern gcc_jit_struct *
+gcc_jit_type_is_struct (gcc_jit_type *type);
+extern ssize_t
+gcc_jit_vector_type_get_num_units (gcc_jit_vector_type *vector_type);
+extern gcc_jit_type *
+gcc_jit_vector_type_get_element_type (gcc_jit_vector_type *vector_type);
+extern gcc_jit_type *
+gcc_jit_type_unqualified (gcc_jit_type *type);
+
 #ifdef __cplusplus
 }
 #endif /* __cplusplus */
diff --git a/gcc/jit/libgccjit.map b/gcc/jit/libgccjit.map
index a6e67e781a4..84d40f5a636 100644
--- a/gcc/jit/libgccjit.map
+++ b/gcc/jit/libgccjit.map
@@ -192,3 +192,24 @@ LIBGCCJIT_ABI_14 {
   global:
     gcc_jit_global_set_initializer;
 } LIBGCCJIT_ABI_13;
+
+LIBGCCJIT_ABI_15 {
+  global:
+    gcc_jit_function_get_return_type;
+    gcc_jit_function_get_param_count;
+    gcc_jit_function_type_get_return_type;
+    gcc_jit_function_type_get_param_count;
+    gcc_jit_function_type_get_param_type;
+    gcc_jit_type_unqualified;
+    gcc_jit_type_is_array;
+    gcc_jit_type_is_bool;
+    gcc_jit_type_is_function_ptr_type;
+    gcc_jit_type_is_int;
+    gcc_jit_type_is_pointer;
+    gcc_jit_type_is_vector;
+    gcc_jit_vector_type_get_element_type;
+    gcc_jit_vector_type_get_num_units;
+    gcc_jit_struct_get_field;
+    gcc_jit_type_is_struct;
+    gcc_jit_struct_get_field_count;
+} LIBGCCJIT_ABI_14;
diff --git a/gcc/testsuite/jit.dg/all-non-failing-tests.h b/gcc/testsuite/jit.dg/all-non-failing-tests.h
index 4202eb7798b..a269144d2df 100644
--- a/gcc/testsuite/jit.dg/all-non-failing-tests.h
+++ b/gcc/testsuite/jit.dg/all-non-failing-tests.h
@@ -258,6 +258,13 @@
 #undef create_code
 #undef verify_code
 
+/* test-reflection.c */
+#define create_code create_code_reflection
+#define verify_code verify_code_reflection
+#include "test-reflection.c"
+#undef create_code
+#undef verify_code
+
 /* test-string-literal.c */
 #define create_code create_code_string_literal
 #define verify_code verify_code_string_literal
@@ -424,6 +431,9 @@ const struct testcase testcases[] = {
   {"reading_struct ",
    create_code_reading_struct ,
    verify_code_reading_struct },
+  {"reflection",
+   create_code_reflection ,
+   verify_code_reflection },
   {"string_literal",
    create_code_string_literal,
    verify_code_string_literal},
diff --git a/gcc/testsuite/jit.dg/test-reflection.c b/gcc/testsuite/jit.dg/test-reflection.c
new file mode 100644
index 00000000000..40a5c43076d
--- /dev/null
+++ b/gcc/testsuite/jit.dg/test-reflection.c
@@ -0,0 +1,89 @@
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "libgccjit.h"
+
+#include "harness.h"
+
+void
+create_code (gcc_jit_context *ctxt, void *user_data)
+{
+  /* Do nothing.  */
+}
+
+void
+verify_code (gcc_jit_context *ctxt, gcc_jit_result *result)
+{
+  /* Get the built-in functions.  */
+  gcc_jit_function *builtin_sin =
+    gcc_jit_context_get_builtin_function (ctxt, "sin");
+
+  CHECK_VALUE (gcc_jit_function_get_param_count(builtin_sin), 1);
+
+  gcc_jit_type *double_type =
+    gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_DOUBLE);
+  CHECK_VALUE (gcc_jit_function_get_return_type(builtin_sin), double_type);
+  CHECK (!gcc_jit_type_is_int(double_type));
+
+  gcc_jit_type *bool_type =
+    gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_BOOL);
+  CHECK (gcc_jit_type_is_bool(bool_type));
+  CHECK (!gcc_jit_type_is_int(bool_type));
+
+  gcc_jit_type *aligned_bool_type =
+    gcc_jit_type_get_aligned(gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_BOOL), 8);
+  CHECK (gcc_jit_type_is_bool(aligned_bool_type));
+  CHECK (bool_type != aligned_bool_type);
+  CHECK_VALUE (gcc_jit_type_unqualified(aligned_bool_type), bool_type);
+
+  CHECK_VALUE (gcc_jit_type_unqualified(gcc_jit_type_get_const(bool_type)), bool_type);
+  CHECK_VALUE (gcc_jit_type_unqualified(gcc_jit_type_get_volatile(bool_type)), bool_type);
+
+  gcc_jit_type *int64 =
+    gcc_jit_context_get_int_type(ctxt, 8, 1);
+  CHECK (gcc_jit_type_is_int(int64));
+  gcc_jit_type *uint64 =
+    gcc_jit_context_get_int_type(ctxt, 8, 0);
+  CHECK (gcc_jit_type_is_int(uint64));
+  gcc_jit_type *int8 =
+    gcc_jit_context_get_int_type(ctxt, 1, 1);
+  CHECK (gcc_jit_type_is_int(int8));
+  gcc_jit_type *uint8 =
+    gcc_jit_context_get_int_type(ctxt, 1, 0);
+  CHECK (gcc_jit_type_is_int(uint8));
+
+  CHECK (!gcc_jit_type_is_vector(double_type));
+  gcc_jit_type *vec_type = gcc_jit_type_get_vector (double_type, 4);
+  gcc_jit_vector_type *vector_type = gcc_jit_type_is_vector(vec_type);
+  CHECK (vector_type);
+  CHECK (vec_type != double_type);
+  CHECK_VALUE (gcc_jit_vector_type_get_element_type(vector_type), double_type);
+  CHECK_VALUE (gcc_jit_vector_type_get_num_units(vector_type), 4);
+
+  CHECK (!gcc_jit_type_is_pointer(double_type));
+  CHECK_VALUE (gcc_jit_type_is_pointer(gcc_jit_type_get_pointer(double_type)), double_type);
+
+  gcc_jit_type* params[2] = {int8, uint64};
+  gcc_jit_type *function_ptr_type = gcc_jit_context_new_function_ptr_type(ctxt, NULL, int64, 2, params, 0);
+  gcc_jit_function_type *function_type = gcc_jit_type_is_function_ptr_type (function_ptr_type);
+  CHECK (function_type);
+  int param_count = gcc_jit_function_type_get_param_count(function_type);
+  CHECK_VALUE (param_count, 2);
+  gcc_jit_type *return_type = gcc_jit_function_type_get_return_type(function_type);
+  CHECK_VALUE (return_type, int64);
+  gcc_jit_type *param1 = gcc_jit_function_type_get_param_type(function_type, 0);
+  CHECK_VALUE (param1, int8);
+  gcc_jit_type *param2 = gcc_jit_function_type_get_param_type(function_type, 1);
+  CHECK_VALUE (param2, uint64);
+
+  gcc_jit_field *field1 = gcc_jit_context_new_field (ctxt, NULL, uint64, "field1");
+  gcc_jit_field *field2 = gcc_jit_context_new_field (ctxt, NULL, double_type, "field2");
+  gcc_jit_field *fields[2] = { field1, field2 };
+  gcc_jit_struct *struct_type = gcc_jit_context_new_struct_type (ctxt, NULL, "testStruct", 2, fields);
+  CHECK_VALUE (gcc_jit_struct_get_field_count(struct_type), 2);
+  CHECK_VALUE (gcc_jit_struct_get_field(struct_type, 0), field1);
+  CHECK_VALUE (gcc_jit_struct_get_field(struct_type, 1), field2);
+  gcc_jit_struct *struct_ty = gcc_jit_type_is_struct(gcc_jit_struct_as_type(struct_type));
+  CHECK_VALUE (struct_ty, struct_type);
+}
+
-- 
2.28.0


^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re: [PATCH] libgccjit: add some reflection functions in the jit C api
  2020-10-15 17:39         ` Antoni Boucher
@ 2020-10-15 18:04           ` Andrea Corallo
  2020-10-15 21:52           ` David Malcolm
  1 sibling, 0 replies; 35+ messages in thread
From: Andrea Corallo @ 2020-10-15 18:04 UTC (permalink / raw)
  To: Antoni Boucher; +Cc: Antoni Boucher via Jit, David Malcolm, gcc-patches

Antoni Boucher <bouanto@zoho.com> writes:

> Thanks. I updated the patch with these changes.
>
> Is there any tool to automatically check the style?

Yes, we have in contrib check_GNU_style.sh and check_GNU_style.py.

  Andrea

^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re: [PATCH] libgccjit: add some reflection functions in the jit C api
  2020-10-15 17:39         ` Antoni Boucher
  2020-10-15 18:04           ` Andrea Corallo
@ 2020-10-15 21:52           ` David Malcolm
  2020-10-17  0:41             ` Antoni Boucher
  2020-11-03 22:13             ` Antoni Boucher
  1 sibling, 2 replies; 35+ messages in thread
From: David Malcolm @ 2020-10-15 21:52 UTC (permalink / raw)
  To: Antoni Boucher, Andrea Corallo; +Cc: Antoni Boucher via Jit, gcc-patches

On Thu, 2020-10-15 at 13:39 -0400, Antoni Boucher wrote:
> Thanks. I updated the patch with these changes.

Thanks for patch; review below.  Sorry if it seems excessively nitpicky
in places.

> 2020-09-1  Antoni Boucher  <bouanto@zoho.com>
> 
>     gcc/jit/
>             PR target/96889
>             * docs/topics/compatibility.rst (LIBGCCJIT_ABI_14): New ABI tag.

15 now.

>             * docs/topics/functions.rst: Add documentation for the
>             functions gcc_jit_function_get_return_type and
>             gcc_jit_function_get_param_count
>             * libgccjit.c: New functions:
>               * gcc_jit_function_get_return_type;
>               * gcc_jit_function_get_param_count;
>               * gcc_jit_function_type_get_return_type;
>               * gcc_jit_function_type_get_param_count;
>               * gcc_jit_function_type_get_param_type;
>               * gcc_jit_type_unqualified;
>               * gcc_jit_type_is_array;
>               * gcc_jit_type_is_bool;
>               * gcc_jit_type_is_function_ptr_type;
>               * gcc_jit_type_is_int;
>               * gcc_jit_type_is_pointer;
>               * gcc_jit_type_is_vector;
>               * gcc_jit_vector_type_get_element_type;
>               * gcc_jit_vector_type_get_num_units;
>               * gcc_jit_struct_get_field;
>               * gcc_jit_type_is_struct;
>               * gcc_jit_struct_get_field_count;

This isn't valid ChangeLog format; it will fail the git hooks.

>             * libgccjit.h

Likewise.

>             * jit-recording.h: New functions (is_struct and is_vector)
>             * libgccjit.map (LIBGCCJIT_ABI_14): New ABI tag.

15 now.

> 
>     gcc/testsuite/
>             PR target/96889
>             * jit.dg/all-non-failing-tests.h: Add test-reflection.c.
>             * jit.dg/test-reflection.c: New test.

[...]


> diff --git a/gcc/jit/docs/topics/functions.rst b/gcc/jit/docs/topics/functions.rst
> index eb40d64010e..9819c28cda2 100644
> --- a/gcc/jit/docs/topics/functions.rst
> +++ b/gcc/jit/docs/topics/functions.rst
> @@ -171,6 +171,16 @@ Functions
>     underlying string, so it is valid to pass in a pointer to an on-stack
>     buffer.
>  
> +.. function::  size_t \
> +               gcc_jit_function_get_param_count (gcc_jit_function *func)
> +
> +   Get the number of parameters of the function.
> +
> +.. function::  gcc_jit_type \*
> +               gcc_jit_function_get_return_type (gcc_jit_function *func)
> +
> +   Get the return type of the function.
> +

The documentation part of the patch is incomplete: it hasn't been
updated to add all the new entrypoints.
Also, the return type of gcc_jit_function_get_param_count is
inconsistent (size_t above, but ssize_t below).


> diff --git a/gcc/jit/jit-recording.h b/gcc/jit/jit-recording.h
> index 30e37aff387..525b8bc921d 100644
> --- a/gcc/jit/jit-recording.h
> +++ b/gcc/jit/jit-recording.h
> @@ -538,7 +538,9 @@ public:
>    virtual bool is_bool () const = 0;
>    virtual type *is_pointer () = 0;
>    virtual type *is_array () = 0;
> +  virtual struct_ *is_struct () { return NULL; }

Can't you use dyn_cast_struct for this?
Or is this about looking through decorated_type? e.g. for const and
volatile variants?

I guess my question is, what is the purpose of gcc_jit_type_is_struct?

>    virtual bool is_void () const { return false; }
> +  virtual vector_type *is_vector () { return NULL; }

Likewise, can't you use dyn_cast_vector_type for this?

>    virtual bool has_known_size () const { return true; }
>  
>    bool is_numeric () const
> @@ -595,6 +597,8 @@ public:
>    bool is_bool () const FINAL OVERRIDE;
>    type *is_pointer () FINAL OVERRIDE { return dereference (); }
>    type *is_array () FINAL OVERRIDE { return NULL; }
> +  vector_type *is_vector () FINAL OVERRIDE { return NULL; }
> +  struct_ *is_struct () FINAL OVERRIDE { return NULL; }

Likewise, and this is redundant, as it's merely copying the base class
implementation.

>    bool is_void () const FINAL OVERRIDE { return m_kind == GCC_JIT_TYPE_VOID; }
>  
>  public:
> @@ -629,6 +633,8 @@ public:
>    bool is_bool () const FINAL OVERRIDE { return false; }
>    type *is_pointer () FINAL OVERRIDE { return m_other_type; }
>    type *is_array () FINAL OVERRIDE { return NULL; }
> +  vector_type *is_vector () FINAL OVERRIDE { return NULL; }
> +  struct_ *is_struct () FINAL OVERRIDE { return NULL; }

Likewise.


> @@ -655,6 +661,7 @@ public:
>    bool is_bool () const FINAL OVERRIDE { return m_other_type->is_bool (); }
>    type *is_pointer () FINAL OVERRIDE { return m_other_type->is_pointer (); }
>    type *is_array () FINAL OVERRIDE { return m_other_type->is_array (); }
> +  struct_ *is_struct () FINAL OVERRIDE { return m_other_type->is_struct (); }

Aha: with a decorated type you look through the decoration.

>  protected:
>    type *m_other_type;
> @@ -737,6 +744,8 @@ public:
>  
>    void replay_into (replayer *) FINAL OVERRIDE;
>  
> +  vector_type *is_vector () FINAL OVERRIDE { return this; }
> +
>  private:
>    string * make_debug_string () FINAL OVERRIDE;
>    void write_reproducer (reproducer &r) FINAL OVERRIDE;
> @@ -765,6 +774,8 @@ class array_type : public type
>    bool is_bool () const FINAL OVERRIDE { return false; }
>    type *is_pointer () FINAL OVERRIDE { return NULL; }
>    type *is_array () FINAL OVERRIDE { return m_element_type; }
> +  vector_type *is_vector () FINAL OVERRIDE { return NULL; }
> +  struct_ *is_struct () FINAL OVERRIDE { return NULL; }

Are these redundant?

>    int num_elements () { return m_num_elements; }
>  
>    void replay_into (replayer *) FINAL OVERRIDE;
> @@ -799,6 +810,8 @@ public:
>    bool is_bool () const FINAL OVERRIDE { return false; }
>    type *is_pointer () FINAL OVERRIDE { return NULL; }
>    type *is_array () FINAL OVERRIDE { return NULL; }
> +  vector_type *is_vector () FINAL OVERRIDE { return NULL; }
> +  struct_ *is_struct () FINAL OVERRIDE { return NULL; }

Likewise.

>    void replay_into (replayer *) FINAL OVERRIDE;
>  
> @@ -912,6 +925,7 @@ public:
>    bool is_bool () const FINAL OVERRIDE { return false; }
>    type *is_pointer () FINAL OVERRIDE { return NULL; }
>    type *is_array () FINAL OVERRIDE { return NULL; }
> +  vector_type *is_vector () FINAL OVERRIDE { return NULL; }

Likewise.

>    bool has_known_size () const FINAL OVERRIDE { return m_fields != NULL; }
>  
> @@ -943,6 +957,8 @@ public:
>  
>    const char *access_as_type (reproducer &r) FINAL OVERRIDE;
>  
> +  struct_ *is_struct () FINAL OVERRIDE { return this; }
> +
>  private:
>    string * make_debug_string () FINAL OVERRIDE;
>    void write_reproducer (reproducer &r) FINAL OVERRIDE;
> diff --git a/gcc/jit/libgccjit.c b/gcc/jit/libgccjit.c
> index a00aefc7108..8e6a9e85ff0 100644
> --- a/gcc/jit/libgccjit.c
> +++ b/gcc/jit/libgccjit.c
> @@ -21,6 +21,7 @@ along with GCC; see the file COPYING3.  If not see
>  #include "config.h"
>  #include "system.h"
>  #include "coretypes.h"
> +#include "tm.h"

Why is this included?  It's not mentioned in the ChangeLog.

>  #include "timevar.h"
>  #include "typed-splay-tree.h"
>  #include "cppbuiltin.h"
> @@ -60,6 +61,14 @@ struct gcc_jit_struct : public gcc::jit::recording::struct_
>  {
>  };
>  
> +struct gcc_jit_function_type : public gcc::jit::recording::function_type
> +{
> +};
> +
> +struct gcc_jit_vector_type : public gcc::jit::recording::vector_type
> +{
> +};
> +

FWIW these aren't mentioned in the ChangeLog either.

>  struct gcc_jit_field : public gcc::jit::recording::field
>  {
>  };
> @@ -510,6 +519,197 @@ gcc_jit_type_get_volatile (gcc_jit_type *type)

[...]

> +/* Public entrypoint.  See description in libgccjit.h.
> +
> +   After error-checking, the real work is done by the
> +   gcc::jit::recording::function_type::get_param_types method, in
> +   jit-recording.c.  */
> +
> +gcc_jit_type *
> +gcc_jit_function_type_get_param_type (gcc_jit_function_type *function_type,
> +				int index)
> +{
> +  RETURN_NULL_IF_FAIL (function_type, NULL, NULL, "NULL struct_type");
> +  int num_params = function_type->get_param_types ().length ();
> +  gcc::jit::recording::context *ctxt = function_type->m_ctxt;

Should check that index >= 0 as well (or make it unsigned).

Given that gcc_jit_function_get_param_count returns ssize_t, should
that be the type of "index"?

> +  RETURN_NULL_IF_FAIL_PRINTF3 (index < num_params,
> +			       ctxt, NULL,
> +			       "index of %d is too large (%s has %d params)",
> +			       index,
> +			       function_type->get_debug_string (),
> +			       num_params);
> +  return (gcc_jit_type *)function_type->get_param_types ()[index];
> +}

[...]

> +extern gcc_jit_field *
> +gcc_jit_struct_get_field (gcc_jit_struct *struct_type,
> +			   int index)
> +{
> +  RETURN_NULL_IF_FAIL (struct_type, NULL, NULL, "NULL struct type");

Similar comments as per gcc_jit_function_type_get_param_type above.
Should check here that index is in range (>=0 and < num fields).

> +  return (gcc_jit_field *)struct_type->get_fields ()->get_field (index);
> +}
> +
> +/* Public entrypoint.  See description in libgccjit.h.
> +
> +   After error-checking, this calls the trivial
> +   gcc::jit::recording::struct_::get_fields method in
> +   jit-recording.h.  */
> +
> +ssize_t
> +gcc_jit_struct_get_field_count (gcc_jit_struct *struct_type)
> +{
> +  RETURN_VAL_IF_FAIL (struct_type, -1, NULL, NULL, "NULL struct type");
> +  return struct_type->get_fields ()->length ();
> +}
> +

[...]

> diff --git a/gcc/jit/libgccjit.h b/gcc/jit/libgccjit.h
> index 7134841bb07..6056d00a3ea 100644
> --- a/gcc/jit/libgccjit.h
> +++ b/gcc/jit/libgccjit.h
> @@ -96,6 +96,12 @@ typedef struct gcc_jit_field gcc_jit_field;
>     the layout for, or an opaque type.  */
>  typedef struct gcc_jit_struct gcc_jit_struct;
>  
> +/* A gcc_jit_function_type encapsulates a function type.  */
> +typedef struct gcc_jit_function_type gcc_jit_function_type;
> +
> +/* A gcc_jit_vector_type encapsulates a vector type.  */
> +typedef struct gcc_jit_vector_type gcc_jit_vector_type;
> +
>  /* A gcc_jit_function encapsulates a function: either one that you're
>     creating yourself, or a reference to one that you're dynamically
>     linking to within the rest of the process.  */
> @@ -586,6 +592,61 @@ gcc_jit_type_get_const (gcc_jit_type *type);
>  extern gcc_jit_type *
>  gcc_jit_type_get_volatile (gcc_jit_type *type);
>  
> +/* Given type "T", return TRUE if the type is an array.  */
> +extern gcc_jit_type *
> +gcc_jit_type_is_array (gcc_jit_type *type);

The comment is unclear; does this actually return the type vs NULL?

As noted above, I think we need to think about what happens on
qualified types; is stripping them the responsibility of the caller?
Should it be?  (I'm thinking "yes", but presumably all this is
motivated by your rust hacking).

Also, there isn't a type "T" here; the param name is "type", and there
isn't a supporting example using "T" as a placeholder.
Maybe just lose the 'Given type "T", ' prefix here and below (unless
giving a example).

> +/* Given type "T", return TRUE if the type is a bool.  */
> +extern int
> +gcc_jit_type_is_bool (gcc_jit_type *type);

I'd prefer "return non-zero" over "return TRUE" (here, and in various
places below).

Does this check for the "bool" type i.e.:
  /* C++'s bool type; also C99's "_Bool" type, aka "bool" if using
     stdbool.h.  */
  GCC_JIT_TYPE_BOOL,
?

> +/* Given type "T", return the function type if it is one.  */

..."or NULL".

> +extern gcc_jit_function_type *
> +gcc_jit_type_is_function_ptr_type (gcc_jit_type *type);
> +
> +/* Given a function type, return its return type.  */
> +extern gcc_jit_type *
> +gcc_jit_function_type_get_return_type (gcc_jit_function_type *function_type);
> +
> +/* Given a function type, return its number of parameters.  */
> +extern ssize_t
> +gcc_jit_function_type_get_param_count (gcc_jit_function_type *function_type);
> +
> +/* Given a function type, return the type of the specified parameter.  */
> +extern gcc_jit_type *
> +gcc_jit_function_type_get_param_type (gcc_jit_function_type *function_type,
> +				int index);
> +
> +/* Given type "T", return the type pointed by the pointer type
> + * or NULL if it's not a pointer.  */
> +extern gcc_jit_type *
> +gcc_jit_type_is_pointer (gcc_jit_type *type);
> +
> +/* Given type "T", return TRUE if the type is an int.  */
> +extern int
> +gcc_jit_type_is_int (gcc_jit_type *type);

I'm not sure I understand what this function does, which suggests it's
misnamed.  The current name suggests that it checks for the C "int"
type, whereas I believe it actually checks for an integral
type.  Should it be:

extern int
gcc_jit_type_is_integral (gcc_jit_type *type);

?

What's the output?  Do you merely need nonzero/zero for boolean, or
information on the width of the type/signedness, or whatnot?  (perhaps
have some out params for extracting width/signedness for when it
returns nonzero?)

Looking at the testcase, it looks like it currently returns false on
the _Bool type.  Is that correct?


> +/* Given type "T", return the unqualified type, i.e. for a
> + * decorated type, return the type it wraps.  */
> +extern gcc_jit_type *
> +gcc_jit_type_unqualified (gcc_jit_type *type);

"decorated" is a term used inside the implementation, but not in the
user-facing docs.

How about:

  /* Given a type, return the unqualified type, removing "const",
"volatile"
     and alignment qualifiers.  */

or somesuch.

> +/* Given type "T", return TRUE if the type is a vector type.  */
> +extern gcc_jit_vector_type *
> +gcc_jit_type_is_vector (gcc_jit_type *type);

As above, this doesn't return TRUE, it's more of a dynamic cast.
Likewise about responsibility for qualifiers.

> +/* Given type "T", return the struct type or NULL.  */
> +extern gcc_jit_struct *
> +gcc_jit_type_is_struct (gcc_jit_type *type);

Wording could be improved as noted above.

> +/* Given a vector type, return the number of units it contains.  */
> +extern ssize_t
> +gcc_jit_vector_type_get_num_units (gcc_jit_vector_type *vector_type);
> +
> +/* Given a vector type, return the type of its elements.  */
> +extern gcc_jit_type *
> +gcc_jit_vector_type_get_element_type (gcc_jit_vector_type *vector_type);
> +

[...]

> @@ -647,6 +708,15 @@ gcc_jit_struct_set_fields (gcc_jit_struct *struct_type,
>  			   int num_fields,
>  			   gcc_jit_field **fields);
>  
> +/* Get a field by index.  */
> +extern gcc_jit_field *
> +gcc_jit_struct_get_field (gcc_jit_struct *struct_type,
> +			   int index);
> +
> +/* Get the number of fields.  */
> +extern ssize_t
> +gcc_jit_struct_get_field_count (gcc_jit_struct *struct_type);

Do we need these for unions?  Or skip them for now?

> @@ -740,6 +810,14 @@ gcc_jit_function_as_object (gcc_jit_function *func);
>  extern gcc_jit_param *
>  gcc_jit_function_get_param (gcc_jit_function *func, int index);
>  
> +/* Get the number of params of a function.  */
> +extern ssize_t
> +gcc_jit_function_get_param_count (gcc_jit_function *func);
> +
> +/* Get the return type of a function.  */
> +extern gcc_jit_type *
> +gcc_jit_function_get_return_type (gcc_jit_function *func);

Are these redundant if there's a way to ask a gcc_jit_function for its
type, and then to use the gcc_jit_function_type_ functions?
(I don't mind if they are)

> @@ -1518,6 +1596,47 @@ gcc_jit_version_minor (void);
>  extern int
>  gcc_jit_version_patchlevel (void);
>  
> +#define LIBGCCJIT_HAVE_gcc_jit_function_reflection
> +
> +/* Reflection functions to get the number of parameters, return type of
> +   a function and whether a type is a bool from the C API.
> +
> +   This API entrypoint was added in LIBGCCJIT_ABI_15; you can test for its
> +   presence using
> +     #ifdef LIBGCCJIT_HAVE_gcc_jit_function_reflection
> +*/

This has become a big mixture of things beyond just function
reflection, so I think I'd prefer it if each entrypoint "funcname" had
its own "LIBGCCJIT_HAVE_funcname" define.  Or just "REFLECTION" rather
than "function_reflection", that's probably simpler.
Note that the existing "HAVE_foo" defines are lowercase "foo" when it's
an actual entrypoint named "foo", and are uppercase otherwise e.g.
LIBGCCJIT_HAVE_SWITCH_STATEMENTS and LIBGCCJIT_HAVE_TIMING_API.

> +extern gcc_jit_type *
> +gcc_jit_function_get_return_type (gcc_jit_function *func);
> +extern ssize_t
> +gcc_jit_function_get_param_count (gcc_jit_function *func);
> +extern gcc_jit_type *
> +gcc_jit_type_is_array (gcc_jit_type *type);
> +extern int
> +gcc_jit_type_is_bool (gcc_jit_type *type);
> +extern gcc_jit_function_type *
> +gcc_jit_type_is_function_ptr_type (gcc_jit_type *type);
> +extern gcc_jit_type *
> +gcc_jit_function_type_get_return_type (gcc_jit_function_type *function_type);
> +extern ssize_t
> +gcc_jit_function_type_get_param_count (gcc_jit_function_type *function_type);
> +extern gcc_jit_type *
> +gcc_jit_function_type_get_param_type (gcc_jit_function_type *function_type,
> +				int index);
> +extern int
> +gcc_jit_type_is_int (gcc_jit_type *type);
> +extern gcc_jit_type *
> +gcc_jit_type_is_pointer (gcc_jit_type *type);
> +extern gcc_jit_vector_type *
> +gcc_jit_type_is_vector (gcc_jit_type *type);
> +extern gcc_jit_struct *
> +gcc_jit_type_is_struct (gcc_jit_type *type);
> +extern ssize_t
> +gcc_jit_vector_type_get_num_units (gcc_jit_vector_type *vector_type);
> +extern gcc_jit_type *
> +gcc_jit_vector_type_get_element_type (gcc_jit_vector_type *vector_type);
> +extern gcc_jit_type *
> +gcc_jit_type_unqualified (gcc_jit_type *type);

Is this part of the patch a duplicate copy of the various things added
above?  Perhaps copy-and-paste error, or am I misreading this?

[...]

Hope this is constructive
Dave


^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re: [PATCH] libgccjit: add some reflection functions in the jit C api
  2020-10-15 21:52           ` David Malcolm
@ 2020-10-17  0:41             ` Antoni Boucher
  2020-11-03 22:13             ` Antoni Boucher
  1 sibling, 0 replies; 35+ messages in thread
From: Antoni Boucher @ 2020-10-17  0:41 UTC (permalink / raw)
  To: David Malcolm; +Cc: Andrea Corallo, Antoni Boucher via Jit, gcc-patches

[-- Attachment #1: Type: text/plain, Size: 19701 bytes --]

Hi.
Thanks for the review. See the comments below.
I attached the updated patch.

On Thu, Oct 15, 2020 at 05:52:33PM -0400, David Malcolm wrote:
>On Thu, 2020-10-15 at 13:39 -0400, Antoni Boucher wrote:
>> Thanks. I updated the patch with these changes.
>
>Thanks for patch; review below.  Sorry if it seems excessively nitpicky
>in places.
>
>> 2020-09-1  Antoni Boucher  <bouanto@zoho.com>
>>
>>     gcc/jit/
>>             PR target/96889
>>             * docs/topics/compatibility.rst (LIBGCCJIT_ABI_14): New ABI tag.
>
>15 now.
>
>>             * docs/topics/functions.rst: Add documentation for the
>>             functions gcc_jit_function_get_return_type and
>>             gcc_jit_function_get_param_count
>>             * libgccjit.c: New functions:
>>               * gcc_jit_function_get_return_type;
>>               * gcc_jit_function_get_param_count;
>>               * gcc_jit_function_type_get_return_type;
>>               * gcc_jit_function_type_get_param_count;
>>               * gcc_jit_function_type_get_param_type;
>>               * gcc_jit_type_unqualified;
>>               * gcc_jit_type_is_array;
>>               * gcc_jit_type_is_bool;
>>               * gcc_jit_type_is_function_ptr_type;
>>               * gcc_jit_type_is_int;
>>               * gcc_jit_type_is_pointer;
>>               * gcc_jit_type_is_vector;
>>               * gcc_jit_vector_type_get_element_type;
>>               * gcc_jit_vector_type_get_num_units;
>>               * gcc_jit_struct_get_field;
>>               * gcc_jit_type_is_struct;
>>               * gcc_jit_struct_get_field_count;
>
>This isn't valid ChangeLog format; it will fail the git hooks.

Is there any way to run that locally to check the format automatically?

>
>>             * libgccjit.h
>
>Likewise.
>
>>             * jit-recording.h: New functions (is_struct and is_vector)
>>             * libgccjit.map (LIBGCCJIT_ABI_14): New ABI tag.
>
>15 now.
>
>>
>>     gcc/testsuite/
>>             PR target/96889
>>             * jit.dg/all-non-failing-tests.h: Add test-reflection.c.
>>             * jit.dg/test-reflection.c: New test.
>
>[...]
>
>
>> diff --git a/gcc/jit/docs/topics/functions.rst b/gcc/jit/docs/topics/functions.rst
>> index eb40d64010e..9819c28cda2 100644
>> --- a/gcc/jit/docs/topics/functions.rst
>> +++ b/gcc/jit/docs/topics/functions.rst
>> @@ -171,6 +171,16 @@ Functions
>>     underlying string, so it is valid to pass in a pointer to an on-stack
>>     buffer.
>>
>> +.. function::  size_t \
>> +               gcc_jit_function_get_param_count (gcc_jit_function *func)
>> +
>> +   Get the number of parameters of the function.
>> +
>> +.. function::  gcc_jit_type \*
>> +               gcc_jit_function_get_return_type (gcc_jit_function *func)
>> +
>> +   Get the return type of the function.
>> +
>
>The documentation part of the patch is incomplete: it hasn't been
>updated to add all the new entrypoints.

Indeed, I wanted some feedback before I write the documentation. I'll 
write it soon.

>Also, the return type of gcc_jit_function_get_param_count is
>inconsistent (size_t above, but ssize_t below).
>
>
>> diff --git a/gcc/jit/jit-recording.h b/gcc/jit/jit-recording.h
>> index 30e37aff387..525b8bc921d 100644
>> --- a/gcc/jit/jit-recording.h
>> +++ b/gcc/jit/jit-recording.h
>> @@ -538,7 +538,9 @@ public:
>>    virtual bool is_bool () const = 0;
>>    virtual type *is_pointer () = 0;
>>    virtual type *is_array () = 0;
>> +  virtual struct_ *is_struct () { return NULL; }
>
>Can't you use dyn_cast_struct for this?

We could, but wouldn't that be inconvenient for the user to call 
gcc_jit_type_unqualified every time they want to call a function such as 
gcc_jit_type_is_struct?
(I don't mind if you prefer to make the call to gcc_jit_type_unqualified 
explicit in user code.)

>Or is this about looking through decorated_type? e.g. for const and
>volatile variants?
>
>I guess my question is, what is the purpose of gcc_jit_type_is_struct?

The purpose is to be able to get information about the fields of the 
struct, if the type is a struct.

>
>>    virtual bool is_void () const { return false; }
>> +  virtual vector_type *is_vector () { return NULL; }
>
>Likewise, can't you use dyn_cast_vector_type for this?

Same as for is_struct().

>>    virtual bool has_known_size () const { return true; }
>>
>>    bool is_numeric () const
>> @@ -595,6 +597,8 @@ public:
>>    bool is_bool () const FINAL OVERRIDE;
>>    type *is_pointer () FINAL OVERRIDE { return dereference (); }
>>    type *is_array () FINAL OVERRIDE { return NULL; }
>> +  vector_type *is_vector () FINAL OVERRIDE { return NULL; }
>> +  struct_ *is_struct () FINAL OVERRIDE { return NULL; }
>
>Likewise, and this is redundant, as it's merely copying the base class
>implementation.
>
>>    bool is_void () const FINAL OVERRIDE { return m_kind == GCC_JIT_TYPE_VOID; }
>>
>>  public:
>> @@ -629,6 +633,8 @@ public:
>>    bool is_bool () const FINAL OVERRIDE { return false; }
>>    type *is_pointer () FINAL OVERRIDE { return m_other_type; }
>>    type *is_array () FINAL OVERRIDE { return NULL; }
>> +  vector_type *is_vector () FINAL OVERRIDE { return NULL; }
>> +  struct_ *is_struct () FINAL OVERRIDE { return NULL; }
>
>Likewise.
>
>
>> @@ -655,6 +661,7 @@ public:
>>    bool is_bool () const FINAL OVERRIDE { return m_other_type->is_bool (); }
>>    type *is_pointer () FINAL OVERRIDE { return m_other_type->is_pointer (); }
>>    type *is_array () FINAL OVERRIDE { return m_other_type->is_array (); }
>> +  struct_ *is_struct () FINAL OVERRIDE { return m_other_type->is_struct (); }
>
>Aha: with a decorated type you look through the decoration.
>
>>  protected:
>>    type *m_other_type;
>> @@ -737,6 +744,8 @@ public:
>>
>>    void replay_into (replayer *) FINAL OVERRIDE;
>>
>> +  vector_type *is_vector () FINAL OVERRIDE { return this; }
>> +
>>  private:
>>    string * make_debug_string () FINAL OVERRIDE;
>>    void write_reproducer (reproducer &r) FINAL OVERRIDE;
>> @@ -765,6 +774,8 @@ class array_type : public type
>>    bool is_bool () const FINAL OVERRIDE { return false; }
>>    type *is_pointer () FINAL OVERRIDE { return NULL; }
>>    type *is_array () FINAL OVERRIDE { return m_element_type; }
>> +  vector_type *is_vector () FINAL OVERRIDE { return NULL; }
>> +  struct_ *is_struct () FINAL OVERRIDE { return NULL; }
>
>Are these redundant?
>
>>    int num_elements () { return m_num_elements; }
>>
>>    void replay_into (replayer *) FINAL OVERRIDE;
>> @@ -799,6 +810,8 @@ public:
>>    bool is_bool () const FINAL OVERRIDE { return false; }
>>    type *is_pointer () FINAL OVERRIDE { return NULL; }
>>    type *is_array () FINAL OVERRIDE { return NULL; }
>> +  vector_type *is_vector () FINAL OVERRIDE { return NULL; }
>> +  struct_ *is_struct () FINAL OVERRIDE { return NULL; }
>
>Likewise.
>
>>    void replay_into (replayer *) FINAL OVERRIDE;
>>
>> @@ -912,6 +925,7 @@ public:
>>    bool is_bool () const FINAL OVERRIDE { return false; }
>>    type *is_pointer () FINAL OVERRIDE { return NULL; }
>>    type *is_array () FINAL OVERRIDE { return NULL; }
>> +  vector_type *is_vector () FINAL OVERRIDE { return NULL; }
>
>Likewise.
>
>>    bool has_known_size () const FINAL OVERRIDE { return m_fields != NULL; }
>>
>> @@ -943,6 +957,8 @@ public:
>>
>>    const char *access_as_type (reproducer &r) FINAL OVERRIDE;
>>
>> +  struct_ *is_struct () FINAL OVERRIDE { return this; }
>> +
>>  private:
>>    string * make_debug_string () FINAL OVERRIDE;
>>    void write_reproducer (reproducer &r) FINAL OVERRIDE;
>> diff --git a/gcc/jit/libgccjit.c b/gcc/jit/libgccjit.c
>> index a00aefc7108..8e6a9e85ff0 100644
>> --- a/gcc/jit/libgccjit.c
>> +++ b/gcc/jit/libgccjit.c
>> @@ -21,6 +21,7 @@ along with GCC; see the file COPYING3.  If not see
>>  #include "config.h"
>>  #include "system.h"
>>  #include "coretypes.h"
>> +#include "tm.h"
>
>Why is this included?  It's not mentioned in the ChangeLog.

Leftover. I removed it.

>>  #include "timevar.h"
>>  #include "typed-splay-tree.h"
>>  #include "cppbuiltin.h"
>> @@ -60,6 +61,14 @@ struct gcc_jit_struct : public gcc::jit::recording::struct_
>>  {
>>  };
>>
>> +struct gcc_jit_function_type : public gcc::jit::recording::function_type
>> +{
>> +};
>> +
>> +struct gcc_jit_vector_type : public gcc::jit::recording::vector_type
>> +{
>> +};
>> +
>
>FWIW these aren't mentioned in the ChangeLog either.
>
>>  struct gcc_jit_field : public gcc::jit::recording::field
>>  {
>>  };
>> @@ -510,6 +519,197 @@ gcc_jit_type_get_volatile (gcc_jit_type *type)
>
>[...]
>
>> +/* Public entrypoint.  See description in libgccjit.h.
>> +
>> +   After error-checking, the real work is done by the
>> +   gcc::jit::recording::function_type::get_param_types method, in
>> +   jit-recording.c.  */
>> +
>> +gcc_jit_type *
>> +gcc_jit_function_type_get_param_type (gcc_jit_function_type *function_type,
>> +				int index)
>> +{
>> +  RETURN_NULL_IF_FAIL (function_type, NULL, NULL, "NULL struct_type");
>> +  int num_params = function_type->get_param_types ().length ();
>> +  gcc::jit::recording::context *ctxt = function_type->m_ctxt;
>
>Should check that index >= 0 as well (or make it unsigned).
>
>Given that gcc_jit_function_get_param_count returns ssize_t, should
>that be the type of "index"?

For those, I had this question in a previous email:

By the way, that seemed off to return NULL for the function returning a 
size_t to indicate an error. So I changed it to return -1 (and return type to
ssize_t). Is that the proper way to indicate an error?

Once I know the answer for this error handling question, I'll fix the 
checks and types.

>> +  RETURN_NULL_IF_FAIL_PRINTF3 (index < num_params,
>> +			       ctxt, NULL,
>> +			       "index of %d is too large (%s has %d params)",
>> +			       index,
>> +			       function_type->get_debug_string (),
>> +			       num_params);
>> +  return (gcc_jit_type *)function_type->get_param_types ()[index];
>> +}
>
>[...]
>
>> +extern gcc_jit_field *
>> +gcc_jit_struct_get_field (gcc_jit_struct *struct_type,
>> +			   int index)
>> +{
>> +  RETURN_NULL_IF_FAIL (struct_type, NULL, NULL, "NULL struct type");
>
>Similar comments as per gcc_jit_function_type_get_param_type above.
>Should check here that index is in range (>=0 and < num fields).

Same as for gcc_jit_function_type_get_param_type.

>> +  return (gcc_jit_field *)struct_type->get_fields ()->get_field (index);
>> +}
>> +
>> +/* Public entrypoint.  See description in libgccjit.h.
>> +
>> +   After error-checking, this calls the trivial
>> +   gcc::jit::recording::struct_::get_fields method in
>> +   jit-recording.h.  */
>> +
>> +ssize_t
>> +gcc_jit_struct_get_field_count (gcc_jit_struct *struct_type)
>> +{
>> +  RETURN_VAL_IF_FAIL (struct_type, -1, NULL, NULL, "NULL struct type");
>> +  return struct_type->get_fields ()->length ();
>> +}
>> +
>
>[...]
>
>> diff --git a/gcc/jit/libgccjit.h b/gcc/jit/libgccjit.h
>> index 7134841bb07..6056d00a3ea 100644
>> --- a/gcc/jit/libgccjit.h
>> +++ b/gcc/jit/libgccjit.h
>> @@ -96,6 +96,12 @@ typedef struct gcc_jit_field gcc_jit_field;
>>     the layout for, or an opaque type.  */
>>  typedef struct gcc_jit_struct gcc_jit_struct;
>>
>> +/* A gcc_jit_function_type encapsulates a function type.  */
>> +typedef struct gcc_jit_function_type gcc_jit_function_type;
>> +
>> +/* A gcc_jit_vector_type encapsulates a vector type.  */
>> +typedef struct gcc_jit_vector_type gcc_jit_vector_type;
>> +
>>  /* A gcc_jit_function encapsulates a function: either one that you're
>>     creating yourself, or a reference to one that you're dynamically
>>     linking to within the rest of the process.  */
>> @@ -586,6 +592,61 @@ gcc_jit_type_get_const (gcc_jit_type *type);
>>  extern gcc_jit_type *
>>  gcc_jit_type_get_volatile (gcc_jit_type *type);
>>
>> +/* Given type "T", return TRUE if the type is an array.  */
>> +extern gcc_jit_type *
>> +gcc_jit_type_is_array (gcc_jit_type *type);
>
>The comment is unclear; does this actually return the type vs NULL?
>
>As noted above, I think we need to think about what happens on
>qualified types; is stripping them the responsibility of the caller?
>Should it be?  (I'm thinking "yes", but presumably all this is
>motivated by your rust hacking).

As said above, I don't mind if you prefer to make that a responsibility 
of the caller. I just thought it was more convenient.

>Also, there isn't a type "T" here; the param name is "type", and there
>isn't a supporting example using "T" as a placeholder.
>Maybe just lose the 'Given type "T", ' prefix here and below (unless
>giving a example).
>
>> +/* Given type "T", return TRUE if the type is a bool.  */
>> +extern int
>> +gcc_jit_type_is_bool (gcc_jit_type *type);
>
>I'd prefer "return non-zero" over "return TRUE" (here, and in various
>places below).
>
>Does this check for the "bool" type i.e.:
>  /* C++'s bool type; also C99's "_Bool" type, aka "bool" if using
>     stdbool.h.  */
>  GCC_JIT_TYPE_BOOL,
>?
>
>> +/* Given type "T", return the function type if it is one.  */
>
>..."or NULL".
>
>> +extern gcc_jit_function_type *
>> +gcc_jit_type_is_function_ptr_type (gcc_jit_type *type);
>> +
>> +/* Given a function type, return its return type.  */
>> +extern gcc_jit_type *
>> +gcc_jit_function_type_get_return_type (gcc_jit_function_type *function_type);
>> +
>> +/* Given a function type, return its number of parameters.  */
>> +extern ssize_t
>> +gcc_jit_function_type_get_param_count (gcc_jit_function_type *function_type);
>> +
>> +/* Given a function type, return the type of the specified parameter.  */
>> +extern gcc_jit_type *
>> +gcc_jit_function_type_get_param_type (gcc_jit_function_type *function_type,
>> +				int index);
>> +
>> +/* Given type "T", return the type pointed by the pointer type
>> + * or NULL if it's not a pointer.  */
>> +extern gcc_jit_type *
>> +gcc_jit_type_is_pointer (gcc_jit_type *type);
>> +
>> +/* Given type "T", return TRUE if the type is an int.  */
>> +extern int
>> +gcc_jit_type_is_int (gcc_jit_type *type);
>
>I'm not sure I understand what this function does, which suggests it's
>misnamed.  The current name suggests that it checks for the C "int"
>type, whereas I believe it actually checks for an integral
>type.  Should it be:
>
>extern int
>gcc_jit_type_is_integral (gcc_jit_type *type);
>
>?

Yes.

>What's the output?  Do you merely need nonzero/zero for boolean, or
>information on the width of the type/signedness, or whatnot?  (perhaps
>have some out params for extracting width/signedness for when it
>returns nonzero?)

At some point, I wanted to add that, but I gave up (I don't remember 
why).

>Looking at the testcase, it looks like it currently returns false on
>the _Bool type.  Is that correct?

Yes. There's a gcc_jit_type_is_bool function to check for that.

>> +/* Given type "T", return the unqualified type, i.e. for a
>> + * decorated type, return the type it wraps.  */
>> +extern gcc_jit_type *
>> +gcc_jit_type_unqualified (gcc_jit_type *type);
>
>"decorated" is a term used inside the implementation, but not in the
>user-facing docs.
>
>How about:
>
>  /* Given a type, return the unqualified type, removing "const",
>"volatile"
>     and alignment qualifiers.  */
>
>or somesuch.
>
>> +/* Given type "T", return TRUE if the type is a vector type.  */
>> +extern gcc_jit_vector_type *
>> +gcc_jit_type_is_vector (gcc_jit_type *type);
>
>As above, this doesn't return TRUE, it's more of a dynamic cast.
>Likewise about responsibility for qualifiers.
>
>> +/* Given type "T", return the struct type or NULL.  */
>> +extern gcc_jit_struct *
>> +gcc_jit_type_is_struct (gcc_jit_type *type);
>
>Wording could be improved as noted above.
>
>> +/* Given a vector type, return the number of units it contains.  */
>> +extern ssize_t
>> +gcc_jit_vector_type_get_num_units (gcc_jit_vector_type *vector_type);
>> +
>> +/* Given a vector type, return the type of its elements.  */
>> +extern gcc_jit_type *
>> +gcc_jit_vector_type_get_element_type (gcc_jit_vector_type *vector_type);
>> +
>
>[...]
>
>> @@ -647,6 +708,15 @@ gcc_jit_struct_set_fields (gcc_jit_struct *struct_type,
>>  			   int num_fields,
>>  			   gcc_jit_field **fields);
>>
>> +/* Get a field by index.  */
>> +extern gcc_jit_field *
>> +gcc_jit_struct_get_field (gcc_jit_struct *struct_type,
>> +			   int index);
>> +
>> +/* Get the number of fields.  */
>> +extern ssize_t
>> +gcc_jit_struct_get_field_count (gcc_jit_struct *struct_type);
>
>Do we need these for unions?  Or skip them for now?

Let's skip them for now.

>> @@ -740,6 +810,14 @@ gcc_jit_function_as_object (gcc_jit_function *func);
>>  extern gcc_jit_param *
>>  gcc_jit_function_get_param (gcc_jit_function *func, int index);
>>
>> +/* Get the number of params of a function.  */
>> +extern ssize_t
>> +gcc_jit_function_get_param_count (gcc_jit_function *func);
>> +
>> +/* Get the return type of a function.  */
>> +extern gcc_jit_type *
>> +gcc_jit_function_get_return_type (gcc_jit_function *func);
>
>Are these redundant if there's a way to ask a gcc_jit_function for its
>type, and then to use the gcc_jit_function_type_ functions?
>(I don't mind if they are)

They're kind of redundant, but I'm not sure what would be the way to 
remove them. I would need a way to create a gcc_jit_function_type from a 
gcc_jit_function.

>> @@ -1518,6 +1596,47 @@ gcc_jit_version_minor (void);
>>  extern int
>>  gcc_jit_version_patchlevel (void);
>>
>> +#define LIBGCCJIT_HAVE_gcc_jit_function_reflection
>> +
>> +/* Reflection functions to get the number of parameters, return type of
>> +   a function and whether a type is a bool from the C API.
>> +
>> +   This API entrypoint was added in LIBGCCJIT_ABI_15; you can test for its
>> +   presence using
>> +     #ifdef LIBGCCJIT_HAVE_gcc_jit_function_reflection
>> +*/
>
>This has become a big mixture of things beyond just function
>reflection, so I think I'd prefer it if each entrypoint "funcname" had
>its own "LIBGCCJIT_HAVE_funcname" define.  Or just "REFLECTION" rather
>than "function_reflection", that's probably simpler.
>Note that the existing "HAVE_foo" defines are lowercase "foo" when it's
>an actual entrypoint named "foo", and are uppercase otherwise e.g.
>LIBGCCJIT_HAVE_SWITCH_STATEMENTS and LIBGCCJIT_HAVE_TIMING_API.
>
>> +extern gcc_jit_type *
>> +gcc_jit_function_get_return_type (gcc_jit_function *func);
>> +extern ssize_t
>> +gcc_jit_function_get_param_count (gcc_jit_function *func);
>> +extern gcc_jit_type *
>> +gcc_jit_type_is_array (gcc_jit_type *type);
>> +extern int
>> +gcc_jit_type_is_bool (gcc_jit_type *type);
>> +extern gcc_jit_function_type *
>> +gcc_jit_type_is_function_ptr_type (gcc_jit_type *type);
>> +extern gcc_jit_type *
>> +gcc_jit_function_type_get_return_type (gcc_jit_function_type *function_type);
>> +extern ssize_t
>> +gcc_jit_function_type_get_param_count (gcc_jit_function_type *function_type);
>> +extern gcc_jit_type *
>> +gcc_jit_function_type_get_param_type (gcc_jit_function_type *function_type,
>> +				int index);
>> +extern int
>> +gcc_jit_type_is_int (gcc_jit_type *type);
>> +extern gcc_jit_type *
>> +gcc_jit_type_is_pointer (gcc_jit_type *type);
>> +extern gcc_jit_vector_type *
>> +gcc_jit_type_is_vector (gcc_jit_type *type);
>> +extern gcc_jit_struct *
>> +gcc_jit_type_is_struct (gcc_jit_type *type);
>> +extern ssize_t
>> +gcc_jit_vector_type_get_num_units (gcc_jit_vector_type *vector_type);
>> +extern gcc_jit_type *
>> +gcc_jit_vector_type_get_element_type (gcc_jit_vector_type *vector_type);
>> +extern gcc_jit_type *
>> +gcc_jit_type_unqualified (gcc_jit_type *type);
>
>Is this part of the patch a duplicate copy of the various things added
>above?  Perhaps copy-and-paste error, or am I misreading this?
>
>[...]
>
>Hope this is constructive
>Dave
>

[-- Attachment #2: 0001-This-patch-add-some-reflection-functions-in-the-jit-.patch --]
[-- Type: text/plain, Size: 25046 bytes --]

From ddb9470c7106213fbf50f00dedaffd0e4508a73b Mon Sep 17 00:00:00 2001
From: Antoni Boucher <bouanto@zoho.com>
Date: Sat, 1 Aug 2020 17:52:17 -0400
Subject: [PATCH] This patch add some reflection functions in the jit C api
 [PR96889]

2020-09-1  Antoni Boucher  <bouanto@zoho.com>

    gcc/jit/
            PR target/96889
            * docs/topics/compatibility.rst (LIBGCCJIT_ABI_15): New ABI tag.
            * docs/topics/functions.rst: Add documentation for the
            functions gcc_jit_function_get_return_type and
            gcc_jit_function_get_param_count
            * libgccjit.c:
            (gcc_jit_function_get_return_type, gcc_jit_function_get_param_count,
            gcc_jit_function_type_get_return_type,
            gcc_jit_function_type_get_param_count,
            gcc_jit_function_type_get_param_type, gcc_jit_type_unqualified,
            gcc_jit_type_is_array, gcc_jit_type_is_bool,
            gcc_jit_type_is_function_ptr_type, gcc_jit_type_is_int,
            gcc_jit_type_is_pointer, gcc_jit_type_is_vector,
            gcc_jit_vector_type_get_element_type,
            gcc_jit_vector_type_get_num_units, gcc_jit_struct_get_field,
            gcc_jit_type_is_struct, gcc_jit_struct_get_field_count): New
            functions.
            (struct gcc_jit_function_type, struct gcc_jit_vector_type):
            New types.
            * libgccjit.h:
            (gcc_jit_function_get_return_type, gcc_jit_function_get_param_count,
            gcc_jit_function_type_get_return_type,
            gcc_jit_function_type_get_param_count,
            gcc_jit_function_type_get_param_type, gcc_jit_type_unqualified,
            gcc_jit_type_is_array, gcc_jit_type_is_bool,
            gcc_jit_type_is_function_ptr_type, gcc_jit_type_is_int,
            gcc_jit_type_is_pointer, gcc_jit_type_is_vector,
            gcc_jit_vector_type_get_element_type,
            gcc_jit_vector_type_get_num_units, gcc_jit_struct_get_field,
            gcc_jit_type_is_struct, gcc_jit_struct_get_field_count): New
            function declarations.
            (struct gcc_jit_function_type, struct gcc_jit_vector_type):
            New types.
            * jit-recording.h: New functions (is_struct and is_vector)
            * libgccjit.map (LIBGCCJIT_ABI_15): New ABI tag.

    gcc/testsuite/
            PR target/96889
            * jit.dg/all-non-failing-tests.h: Add test-reflection.c.
            * jit.dg/test-reflection.c: New test.
---
 gcc/jit/docs/topics/compatibility.rst        |  41 +++
 gcc/jit/docs/topics/functions.rst            |  10 +
 gcc/jit/jit-recording.h                      |   7 +
 gcc/jit/libgccjit.c                          | 257 +++++++++++++++++++
 gcc/jit/libgccjit.h                          |  87 +++++++
 gcc/jit/libgccjit.map                        |  21 ++
 gcc/testsuite/jit.dg/all-non-failing-tests.h |  10 +
 gcc/testsuite/jit.dg/test-reflection.c       |  89 +++++++
 8 files changed, 522 insertions(+)
 create mode 100644 gcc/testsuite/jit.dg/test-reflection.c

diff --git a/gcc/jit/docs/topics/compatibility.rst b/gcc/jit/docs/topics/compatibility.rst
index 6bfa101ed71..236e5c72d81 100644
--- a/gcc/jit/docs/topics/compatibility.rst
+++ b/gcc/jit/docs/topics/compatibility.rst
@@ -226,3 +226,44 @@ entrypoints:
 --------------------
 ``LIBGCCJIT_ABI_14`` covers the addition of
 :func:`gcc_jit_global_set_initializer`
+
+.. _LIBGCCJIT_ABI_15:
+
+``LIBGCCJIT_ABI_15``
+--------------------
+``LIBGCCJIT_ABI_15`` covers the addition of reflection functions via API
+entrypoints:
+
+  * :func:`gcc_jit_function_get_return_type`
+
+  * :func:`gcc_jit_function_get_param_count`
+
+  * :func:`gcc_jit_type_is_array`
+
+  * :func:`gcc_jit_type_is_bool`
+
+  * :func:`gcc_jit_type_is_integral`
+
+  * :func:`gcc_jit_type_is_pointer`
+
+  * :func:`gcc_jit_type_is_struct`
+
+  * :func:`gcc_jit_type_is_vector`
+
+  * :func:`gcc_jit_type_unqualified`
+
+  * :func:`gcc_jit_type_is_function_ptr_type`
+
+  * :func:`gcc_jit_function_type_get_return_type`
+
+  * :func:`gcc_jit_function_type_get_param_count`
+
+  * :func:`gcc_jit_function_type_get_param_type`
+
+  * :func:`gcc_jit_vector_type_get_num_units`
+
+  * :func:`gcc_jit_vector_type_get_element_type`
+
+  * :func:`gcc_jit_struct_get_field`
+
+  * :func:`gcc_jit_struct_get_field_count`
diff --git a/gcc/jit/docs/topics/functions.rst b/gcc/jit/docs/topics/functions.rst
index eb40d64010e..aa6de87282d 100644
--- a/gcc/jit/docs/topics/functions.rst
+++ b/gcc/jit/docs/topics/functions.rst
@@ -171,6 +171,16 @@ Functions
    underlying string, so it is valid to pass in a pointer to an on-stack
    buffer.
 
+.. function::  ssize_t \
+               gcc_jit_function_get_param_count (gcc_jit_function *func)
+
+   Get the number of parameters of the function.
+
+.. function::  gcc_jit_type \*
+               gcc_jit_function_get_return_type (gcc_jit_function *func)
+
+   Get the return type of the function.
+
 Blocks
 ------
 .. type:: gcc_jit_block
diff --git a/gcc/jit/jit-recording.h b/gcc/jit/jit-recording.h
index 30e37aff387..8f494a060ef 100644
--- a/gcc/jit/jit-recording.h
+++ b/gcc/jit/jit-recording.h
@@ -538,7 +538,9 @@ public:
   virtual bool is_bool () const = 0;
   virtual type *is_pointer () = 0;
   virtual type *is_array () = 0;
+  virtual struct_ *is_struct () { return NULL; }
   virtual bool is_void () const { return false; }
+  virtual vector_type *is_vector () { return NULL; }
   virtual bool has_known_size () const { return true; }
 
   bool is_numeric () const
@@ -655,6 +657,7 @@ public:
   bool is_bool () const FINAL OVERRIDE { return m_other_type->is_bool (); }
   type *is_pointer () FINAL OVERRIDE { return m_other_type->is_pointer (); }
   type *is_array () FINAL OVERRIDE { return m_other_type->is_array (); }
+  struct_ *is_struct () FINAL OVERRIDE { return m_other_type->is_struct (); }
 
 protected:
   type *m_other_type;
@@ -737,6 +740,8 @@ public:
 
   void replay_into (replayer *) FINAL OVERRIDE;
 
+  vector_type *is_vector () FINAL OVERRIDE { return this; }
+
 private:
   string * make_debug_string () FINAL OVERRIDE;
   void write_reproducer (reproducer &r) FINAL OVERRIDE;
@@ -943,6 +948,8 @@ public:
 
   const char *access_as_type (reproducer &r) FINAL OVERRIDE;
 
+  struct_ *is_struct () FINAL OVERRIDE { return this; }
+
 private:
   string * make_debug_string () FINAL OVERRIDE;
   void write_reproducer (reproducer &r) FINAL OVERRIDE;
diff --git a/gcc/jit/libgccjit.c b/gcc/jit/libgccjit.c
index a00aefc7108..fc6e77aa68f 100644
--- a/gcc/jit/libgccjit.c
+++ b/gcc/jit/libgccjit.c
@@ -60,6 +60,14 @@ struct gcc_jit_struct : public gcc::jit::recording::struct_
 {
 };
 
+struct gcc_jit_function_type : public gcc::jit::recording::function_type
+{
+};
+
+struct gcc_jit_vector_type : public gcc::jit::recording::vector_type
+{
+};
+
 struct gcc_jit_field : public gcc::jit::recording::field
 {
 };
@@ -510,6 +518,197 @@ gcc_jit_type_get_volatile (gcc_jit_type *type)
   return (gcc_jit_type *)type->get_volatile ();
 }
 
+/* Public entrypoint.  See description in libgccjit.h.
+
+   After error-checking, the real work is done by the
+   gcc::jit::recording::type::is_array method, in
+   jit-recording.c.  */
+
+gcc_jit_type *
+gcc_jit_type_is_array (gcc_jit_type *type)
+{
+  RETURN_NULL_IF_FAIL (type, NULL, NULL, "NULL type");
+
+  return (gcc_jit_type *)type->is_array ();
+}
+
+/* Public entrypoint.  See description in libgccjit.h.
+
+   After error-checking, the real work is done by the
+   gcc::jit::recording::type::is_bool method, in
+   jit-recording.c.  */
+
+int
+gcc_jit_type_is_bool (gcc_jit_type *type)
+{
+  RETURN_VAL_IF_FAIL (type, FALSE, NULL, NULL, "NULL type");
+
+  return type->is_bool ();
+}
+
+/* Public entrypoint.  See description in libgccjit.h.
+
+   After error-checking, the real work is done by the
+   gcc::jit::recording::type::is_pointer method, in
+   jit-recording.c.  */
+
+gcc_jit_type *
+gcc_jit_type_is_pointer (gcc_jit_type *type)
+{
+  RETURN_NULL_IF_FAIL (type, NULL, NULL, "NULL type");
+
+  return (gcc_jit_type *)type->is_pointer ();
+}
+
+/* Public entrypoint.  See description in libgccjit.h.
+
+   After error-checking, the real work is done by the
+   gcc::jit::recording::type::is_int method, in
+   jit-recording.c.  */
+
+int
+gcc_jit_type_is_integral (gcc_jit_type *type)
+{
+  RETURN_VAL_IF_FAIL (type, FALSE, NULL, NULL, "NULL type");
+
+  return type->is_int ();
+}
+
+/* Public entrypoint.  See description in libgccjit.h.
+
+   After error-checking, the real work is done by the
+   gcc::jit::recording::type::is_vector method, in
+   jit-recording.c.  */
+
+gcc_jit_vector_type *
+gcc_jit_type_is_vector (gcc_jit_type *type)
+{
+  RETURN_NULL_IF_FAIL (type, NULL, NULL, "NULL type");
+  gcc::jit::recording::vector_type *vector_type = type->is_vector ();
+  return (gcc_jit_vector_type *)vector_type;
+}
+
+/* Public entrypoint.  See description in libgccjit.h.
+
+   After error-checking, the real work is done by the
+   gcc::jit::recording::type::is_struct method, in
+   jit-recording.c.  */
+
+gcc_jit_struct *
+gcc_jit_type_is_struct (gcc_jit_type *type)
+{
+  RETURN_NULL_IF_FAIL (type, NULL, NULL, "NULL type");
+  gcc::jit::recording::struct_ *struct_type = type->is_struct ();
+  return (gcc_jit_struct *)struct_type;
+}
+
+/* Public entrypoint.  See description in libgccjit.h.
+
+   After error-checking, the real work is done by the
+   gcc::jit::recording::vector_type::get_num_units method, in
+   jit-recording.c.  */
+
+ssize_t
+gcc_jit_vector_type_get_num_units (gcc_jit_vector_type *vector_type)
+{
+  RETURN_VAL_IF_FAIL (vector_type, -1, NULL, NULL, "NULL vector_type");
+  return vector_type->get_num_units ();
+}
+
+/* Public entrypoint.  See description in libgccjit.h.
+
+   After error-checking, the real work is done by the
+   gcc::jit::recording::vector_type::get_element_type method, in
+   jit-recording.c.  */
+
+gcc_jit_type *
+gcc_jit_vector_type_get_element_type (gcc_jit_vector_type *vector_type)
+{
+  RETURN_NULL_IF_FAIL (vector_type, NULL, NULL, "NULL vector_type");
+  return (gcc_jit_type *)vector_type->get_element_type ();
+}
+
+/* Public entrypoint.  See description in libgccjit.h.
+
+   After error-checking, the real work is done by the
+   gcc::jit::recording::type::unqualified method, in
+   jit-recording.c.  */
+
+gcc_jit_type *
+gcc_jit_type_unqualified (gcc_jit_type *type)
+{
+  RETURN_NULL_IF_FAIL (type, NULL, NULL, "NULL type");
+
+  return (gcc_jit_type *)type->unqualified ();
+}
+
+/* Public entrypoint.  See description in libgccjit.h.
+
+   After error-checking, the real work is done by the
+   gcc::jit::recording::type::dyn_cast_function_type method, in
+   jit-recording.c.  */
+
+gcc_jit_function_type *
+gcc_jit_type_is_function_ptr_type (gcc_jit_type *type)
+{
+  RETURN_NULL_IF_FAIL (type, NULL, NULL, "NULL type");
+  gcc::jit::recording::type *func_ptr_type = type->dereference ();
+  RETURN_NULL_IF_FAIL (func_ptr_type, NULL, NULL, "NULL type");
+  gcc::jit::recording::function_type *func_type =
+    func_ptr_type->dyn_cast_function_type ();
+  RETURN_NULL_IF_FAIL (func_type, NULL, NULL, "NULL type");
+
+  return (gcc_jit_function_type *)func_type;
+}
+
+/* Public entrypoint.  See description in libgccjit.h.
+
+   After error-checking, the real work is done by the
+   gcc::jit::recording::function_type::get_return_type method, in
+   jit-recording.c.  */
+
+gcc_jit_type *
+gcc_jit_function_type_get_return_type (gcc_jit_function_type *function_type)
+{
+  RETURN_NULL_IF_FAIL (function_type, NULL, NULL, "NULL struct_type");
+  return (gcc_jit_type *)function_type->get_return_type ();
+}
+
+/* Public entrypoint.  See description in libgccjit.h.
+
+   After error-checking, the real work is done by the
+   gcc::jit::recording::function_type::get_param_types method, in
+   jit-recording.c.  */
+
+ssize_t
+gcc_jit_function_type_get_param_count (gcc_jit_function_type *function_type)
+{
+  RETURN_VAL_IF_FAIL (function_type, -1, NULL, NULL, "NULL struct_type");
+  return function_type->get_param_types ().length ();
+}
+
+/* Public entrypoint.  See description in libgccjit.h.
+
+   After error-checking, the real work is done by the
+   gcc::jit::recording::function_type::get_param_types method, in
+   jit-recording.c.  */
+
+gcc_jit_type *
+gcc_jit_function_type_get_param_type (gcc_jit_function_type *function_type,
+				int index)
+{
+  RETURN_NULL_IF_FAIL (function_type, NULL, NULL, "NULL struct_type");
+  int num_params = function_type->get_param_types ().length ();
+  gcc::jit::recording::context *ctxt = function_type->m_ctxt;
+  RETURN_NULL_IF_FAIL_PRINTF3 (index < num_params,
+			       ctxt, NULL,
+			       "index of %d is too large (%s has %d params)",
+			       index,
+			       function_type->get_debug_string (),
+			       num_params);
+  return (gcc_jit_type *)function_type->get_param_types ()[index];
+}
+
 /* Public entrypoint.  See description in libgccjit.h.
 
    After error-checking, the real work is done by the
@@ -731,6 +930,35 @@ gcc_jit_struct_set_fields (gcc_jit_struct *struct_type,
 			   (gcc::jit::recording::field **)fields);
 }
 
+
+/* Public entrypoint.  See description in libgccjit.h.
+
+   After error-checking, the real work is done by the
+   gcc::jit::recording::fields::get_field method in
+   jit-recording.c.  */
+extern gcc_jit_field *
+gcc_jit_struct_get_field (gcc_jit_struct *struct_type,
+			   int index)
+{
+  RETURN_NULL_IF_FAIL (struct_type, NULL, NULL, "NULL struct type");
+  RETURN_NULL_IF_FAIL (index < struct_type->get_fields ()->length (), NULL,
+				NULL, "NULL struct type");
+  return (gcc_jit_field *)struct_type->get_fields ()->get_field (index);
+}
+
+/* Public entrypoint.  See description in libgccjit.h.
+
+   After error-checking, this calls the trivial
+   gcc::jit::recording::struct_::get_fields method in
+   jit-recording.h.  */
+
+ssize_t
+gcc_jit_struct_get_field_count (gcc_jit_struct *struct_type)
+{
+  RETURN_VAL_IF_FAIL (struct_type, -1, NULL, NULL, "NULL struct type");
+  return struct_type->get_fields ()->length ();
+}
+
 /* Public entrypoint.  See description in libgccjit.h.
 
    After error-checking, the real work is done by the
@@ -1012,6 +1240,35 @@ gcc_jit_function_get_param (gcc_jit_function *func, int index)
   return static_cast <gcc_jit_param *> (func->get_param (index));
 }
 
+/* Public entrypoint.  See description in libgccjit.h.
+
+   After error-checking, the real work is done by the
+   gcc::jit::recording::function::get_params method, in
+   jit-recording.h.
+  */
+
+ssize_t
+gcc_jit_function_get_param_count (gcc_jit_function *func)
+{
+  RETURN_VAL_IF_FAIL (func, -1, NULL, NULL, "NULL function");
+  gcc::jit::recording::context *ctxt = func->m_ctxt;
+  JIT_LOG_FUNC (ctxt->get_logger ());
+  return func->get_params ().length ();
+}
+
+/* Public entrypoint.  See description in libgccjit.h.
+
+   After error-checking, the real work is done by the
+   gcc::jit::recording::function::get_return_type method, in
+   jit-recording.h.  */
+
+gcc_jit_type *
+gcc_jit_function_get_return_type (gcc_jit_function *func)
+{
+    RETURN_NULL_IF_FAIL (func, NULL, NULL, "NULL function");
+    return (gcc_jit_type *)func->get_return_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 7134841bb07..db4ccffb41c 100644
--- a/gcc/jit/libgccjit.h
+++ b/gcc/jit/libgccjit.h
@@ -96,6 +96,12 @@ typedef struct gcc_jit_field gcc_jit_field;
    the layout for, or an opaque type.  */
 typedef struct gcc_jit_struct gcc_jit_struct;
 
+/* A gcc_jit_function_type encapsulates a function type.  */
+typedef struct gcc_jit_function_type gcc_jit_function_type;
+
+/* A gcc_jit_vector_type encapsulates a vector type.  */
+typedef struct gcc_jit_vector_type gcc_jit_vector_type;
+
 /* A gcc_jit_function encapsulates a function: either one that you're
    creating yourself, or a reference to one that you're dynamically
    linking to within the rest of the process.  */
@@ -647,6 +653,15 @@ gcc_jit_struct_set_fields (gcc_jit_struct *struct_type,
 			   int num_fields,
 			   gcc_jit_field **fields);
 
+/* Get a field by index.  */
+extern gcc_jit_field *
+gcc_jit_struct_get_field (gcc_jit_struct *struct_type,
+			   int index);
+
+/* Get the number of fields.  */
+extern ssize_t
+gcc_jit_struct_get_field_count (gcc_jit_struct *struct_type);
+
 /* Unions work similarly to structs.  */
 extern gcc_jit_type *
 gcc_jit_context_new_union_type (gcc_jit_context *ctxt,
@@ -1518,6 +1533,78 @@ gcc_jit_version_minor (void);
 extern int
 gcc_jit_version_patchlevel (void);
 
+#define LIBGCCJIT_HAVE_REFLECTION
+
+/* Reflection functions to get the number of parameters, return type of
+   a function and whether a type is a bool from the C API.
+
+   This API entrypoint was added in LIBGCCJIT_ABI_15; you can test for its
+   presence using
+     #ifdef LIBGCCJIT_HAVE_REFLECTION
+*/
+/* Get the return type of a function.  */
+extern gcc_jit_type *
+gcc_jit_function_get_return_type (gcc_jit_function *func);
+
+/* Get the number of params of a function.  */
+extern ssize_t
+gcc_jit_function_get_param_count (gcc_jit_function *func);
+
+/* Get the element type of an array type or NULL if it's not an array.  */
+extern gcc_jit_type *
+gcc_jit_type_is_array (gcc_jit_type *type);
+
+/* Return non-zero if the type is a bool.  */
+extern int
+gcc_jit_type_is_bool (gcc_jit_type *type);
+
+/* Return the function type if it is one or NULL.  */
+extern gcc_jit_function_type *
+gcc_jit_type_is_function_ptr_type (gcc_jit_type *type);
+
+/* Given a function type, return its return type.  */
+extern gcc_jit_type *
+gcc_jit_function_type_get_return_type (gcc_jit_function_type *function_type);
+
+/* Given a function type, return its number of parameters.  */
+extern ssize_t
+gcc_jit_function_type_get_param_count (gcc_jit_function_type *function_type);
+
+/* Given a function type, return the type of the specified parameter.  */
+extern gcc_jit_type *
+gcc_jit_function_type_get_param_type (gcc_jit_function_type *function_type,
+				int index);
+
+/* Return non-zero if the type is an integral.  */
+extern int
+gcc_jit_type_is_integral (gcc_jit_type *type);
+
+/* Return the type pointed by the pointer type or NULL if it's not a
+ * pointer.  */
+extern gcc_jit_type *
+gcc_jit_type_is_pointer (gcc_jit_type *type);
+
+/* Given a type, return a dynamic cast to a vector type or NULL.  */
+extern gcc_jit_vector_type *
+gcc_jit_type_is_vector (gcc_jit_type *type);
+
+/* Given a type, return a dynamic cast to a struct type or NULL.  */
+extern gcc_jit_struct *
+gcc_jit_type_is_struct (gcc_jit_type *type);
+
+/* Given a vector type, return the number of units it contains.  */
+extern ssize_t
+gcc_jit_vector_type_get_num_units (gcc_jit_vector_type *vector_type);
+
+/* Given a vector type, return the type of its elements.  */
+extern gcc_jit_type *
+gcc_jit_vector_type_get_element_type (gcc_jit_vector_type *vector_type);
+
+/* Given a type, return the unqualified type, removing "const", "volatile"
+ * and alignment qualifiers.  */
+extern gcc_jit_type *
+gcc_jit_type_unqualified (gcc_jit_type *type);
+
 #ifdef __cplusplus
 }
 #endif /* __cplusplus */
diff --git a/gcc/jit/libgccjit.map b/gcc/jit/libgccjit.map
index a6e67e781a4..720b6ca286f 100644
--- a/gcc/jit/libgccjit.map
+++ b/gcc/jit/libgccjit.map
@@ -192,3 +192,24 @@ LIBGCCJIT_ABI_14 {
   global:
     gcc_jit_global_set_initializer;
 } LIBGCCJIT_ABI_13;
+
+LIBGCCJIT_ABI_15 {
+  global:
+    gcc_jit_function_get_return_type;
+    gcc_jit_function_get_param_count;
+    gcc_jit_function_type_get_return_type;
+    gcc_jit_function_type_get_param_count;
+    gcc_jit_function_type_get_param_type;
+    gcc_jit_type_unqualified;
+    gcc_jit_type_is_array;
+    gcc_jit_type_is_bool;
+    gcc_jit_type_is_function_ptr_type;
+    gcc_jit_type_is_integral;
+    gcc_jit_type_is_pointer;
+    gcc_jit_type_is_vector;
+    gcc_jit_vector_type_get_element_type;
+    gcc_jit_vector_type_get_num_units;
+    gcc_jit_struct_get_field;
+    gcc_jit_type_is_struct;
+    gcc_jit_struct_get_field_count;
+} LIBGCCJIT_ABI_14;
diff --git a/gcc/testsuite/jit.dg/all-non-failing-tests.h b/gcc/testsuite/jit.dg/all-non-failing-tests.h
index 4202eb7798b..a269144d2df 100644
--- a/gcc/testsuite/jit.dg/all-non-failing-tests.h
+++ b/gcc/testsuite/jit.dg/all-non-failing-tests.h
@@ -258,6 +258,13 @@
 #undef create_code
 #undef verify_code
 
+/* test-reflection.c */
+#define create_code create_code_reflection
+#define verify_code verify_code_reflection
+#include "test-reflection.c"
+#undef create_code
+#undef verify_code
+
 /* test-string-literal.c */
 #define create_code create_code_string_literal
 #define verify_code verify_code_string_literal
@@ -424,6 +431,9 @@ const struct testcase testcases[] = {
   {"reading_struct ",
    create_code_reading_struct ,
    verify_code_reading_struct },
+  {"reflection",
+   create_code_reflection ,
+   verify_code_reflection },
   {"string_literal",
    create_code_string_literal,
    verify_code_string_literal},
diff --git a/gcc/testsuite/jit.dg/test-reflection.c b/gcc/testsuite/jit.dg/test-reflection.c
new file mode 100644
index 00000000000..b3cf2942f3a
--- /dev/null
+++ b/gcc/testsuite/jit.dg/test-reflection.c
@@ -0,0 +1,89 @@
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "libgccjit.h"
+
+#include "harness.h"
+
+void
+create_code (gcc_jit_context *ctxt, void *user_data)
+{
+  /* Do nothing.  */
+}
+
+void
+verify_code (gcc_jit_context *ctxt, gcc_jit_result *result)
+{
+  /* Get the built-in functions.  */
+  gcc_jit_function *builtin_sin =
+    gcc_jit_context_get_builtin_function (ctxt, "sin");
+
+  CHECK_VALUE (gcc_jit_function_get_param_count(builtin_sin), 1);
+
+  gcc_jit_type *double_type =
+    gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_DOUBLE);
+  CHECK_VALUE (gcc_jit_function_get_return_type(builtin_sin), double_type);
+  CHECK (!gcc_jit_type_is_integral(double_type));
+
+  gcc_jit_type *bool_type =
+    gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_BOOL);
+  CHECK (gcc_jit_type_is_bool(bool_type));
+  CHECK (!gcc_jit_type_is_integral(bool_type));
+
+  gcc_jit_type *aligned_bool_type =
+    gcc_jit_type_get_aligned(gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_BOOL), 8);
+  CHECK (gcc_jit_type_is_bool(aligned_bool_type));
+  CHECK (bool_type != aligned_bool_type);
+  CHECK_VALUE (gcc_jit_type_unqualified(aligned_bool_type), bool_type);
+
+  CHECK_VALUE (gcc_jit_type_unqualified(gcc_jit_type_get_const(bool_type)), bool_type);
+  CHECK_VALUE (gcc_jit_type_unqualified(gcc_jit_type_get_volatile(bool_type)), bool_type);
+
+  gcc_jit_type *int64 =
+    gcc_jit_context_get_int_type(ctxt, 8, 1);
+  CHECK (gcc_jit_type_is_integral(int64));
+  gcc_jit_type *uint64 =
+    gcc_jit_context_get_int_type(ctxt, 8, 0);
+  CHECK (gcc_jit_type_is_integral(uint64));
+  gcc_jit_type *int8 =
+    gcc_jit_context_get_int_type(ctxt, 1, 1);
+  CHECK (gcc_jit_type_is_integral(int8));
+  gcc_jit_type *uint8 =
+    gcc_jit_context_get_int_type(ctxt, 1, 0);
+  CHECK (gcc_jit_type_is_integral(uint8));
+
+  CHECK (!gcc_jit_type_is_vector(double_type));
+  gcc_jit_type *vec_type = gcc_jit_type_get_vector (double_type, 4);
+  gcc_jit_vector_type *vector_type = gcc_jit_type_is_vector(vec_type);
+  CHECK (vector_type);
+  CHECK (vec_type != double_type);
+  CHECK_VALUE (gcc_jit_vector_type_get_element_type(vector_type), double_type);
+  CHECK_VALUE (gcc_jit_vector_type_get_num_units(vector_type), 4);
+
+  CHECK (!gcc_jit_type_is_pointer(double_type));
+  CHECK_VALUE (gcc_jit_type_is_pointer(gcc_jit_type_get_pointer(double_type)), double_type);
+
+  gcc_jit_type* params[2] = {int8, uint64};
+  gcc_jit_type *function_ptr_type = gcc_jit_context_new_function_ptr_type(ctxt, NULL, int64, 2, params, 0);
+  gcc_jit_function_type *function_type = gcc_jit_type_is_function_ptr_type (function_ptr_type);
+  CHECK (function_type);
+  int param_count = gcc_jit_function_type_get_param_count(function_type);
+  CHECK_VALUE (param_count, 2);
+  gcc_jit_type *return_type = gcc_jit_function_type_get_return_type(function_type);
+  CHECK_VALUE (return_type, int64);
+  gcc_jit_type *param1 = gcc_jit_function_type_get_param_type(function_type, 0);
+  CHECK_VALUE (param1, int8);
+  gcc_jit_type *param2 = gcc_jit_function_type_get_param_type(function_type, 1);
+  CHECK_VALUE (param2, uint64);
+
+  gcc_jit_field *field1 = gcc_jit_context_new_field (ctxt, NULL, uint64, "field1");
+  gcc_jit_field *field2 = gcc_jit_context_new_field (ctxt, NULL, double_type, "field2");
+  gcc_jit_field *fields[2] = { field1, field2 };
+  gcc_jit_struct *struct_type = gcc_jit_context_new_struct_type (ctxt, NULL, "testStruct", 2, fields);
+  CHECK_VALUE (gcc_jit_struct_get_field_count(struct_type), 2);
+  CHECK_VALUE (gcc_jit_struct_get_field(struct_type, 0), field1);
+  CHECK_VALUE (gcc_jit_struct_get_field(struct_type, 1), field2);
+  gcc_jit_struct *struct_ty = gcc_jit_type_is_struct(gcc_jit_struct_as_type(struct_type));
+  CHECK_VALUE (struct_ty, struct_type);
+}
+
-- 
2.28.0


^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re: [PATCH] libgccjit: add some reflection functions in the jit C api
  2020-10-15 21:52           ` David Malcolm
  2020-10-17  0:41             ` Antoni Boucher
@ 2020-11-03 22:13             ` Antoni Boucher
  2021-05-13  8:33               ` Martin Liška
  2021-05-13 21:30               ` David Malcolm
  1 sibling, 2 replies; 35+ messages in thread
From: Antoni Boucher @ 2020-11-03 22:13 UTC (permalink / raw)
  To: David Malcolm; +Cc: Andrea Corallo, Antoni Boucher via Jit, gcc-patches

[-- Attachment #1: Type: text/plain, Size: 18266 bytes --]

I was missing a check in gcc_jit_struct_get_field, I added it in this 
new patch.

On Thu, Oct 15, 2020 at 05:52:33PM -0400, David Malcolm wrote:
>On Thu, 2020-10-15 at 13:39 -0400, Antoni Boucher wrote:
>> Thanks. I updated the patch with these changes.
>
>Thanks for patch; review below.  Sorry if it seems excessively nitpicky
>in places.
>
>> 2020-09-1  Antoni Boucher  <bouanto@zoho.com>
>>
>>     gcc/jit/
>>             PR target/96889
>>             * docs/topics/compatibility.rst (LIBGCCJIT_ABI_14): New ABI tag.
>
>15 now.
>
>>             * docs/topics/functions.rst: Add documentation for the
>>             functions gcc_jit_function_get_return_type and
>>             gcc_jit_function_get_param_count
>>             * libgccjit.c: New functions:
>>               * gcc_jit_function_get_return_type;
>>               * gcc_jit_function_get_param_count;
>>               * gcc_jit_function_type_get_return_type;
>>               * gcc_jit_function_type_get_param_count;
>>               * gcc_jit_function_type_get_param_type;
>>               * gcc_jit_type_unqualified;
>>               * gcc_jit_type_is_array;
>>               * gcc_jit_type_is_bool;
>>               * gcc_jit_type_is_function_ptr_type;
>>               * gcc_jit_type_is_int;
>>               * gcc_jit_type_is_pointer;
>>               * gcc_jit_type_is_vector;
>>               * gcc_jit_vector_type_get_element_type;
>>               * gcc_jit_vector_type_get_num_units;
>>               * gcc_jit_struct_get_field;
>>               * gcc_jit_type_is_struct;
>>               * gcc_jit_struct_get_field_count;
>
>This isn't valid ChangeLog format; it will fail the git hooks.
>
>>             * libgccjit.h
>
>Likewise.
>
>>             * jit-recording.h: New functions (is_struct and is_vector)
>>             * libgccjit.map (LIBGCCJIT_ABI_14): New ABI tag.
>
>15 now.
>
>>
>>     gcc/testsuite/
>>             PR target/96889
>>             * jit.dg/all-non-failing-tests.h: Add test-reflection.c.
>>             * jit.dg/test-reflection.c: New test.
>
>[...]
>
>
>> diff --git a/gcc/jit/docs/topics/functions.rst b/gcc/jit/docs/topics/functions.rst
>> index eb40d64010e..9819c28cda2 100644
>> --- a/gcc/jit/docs/topics/functions.rst
>> +++ b/gcc/jit/docs/topics/functions.rst
>> @@ -171,6 +171,16 @@ Functions
>>     underlying string, so it is valid to pass in a pointer to an on-stack
>>     buffer.
>>
>> +.. function::  size_t \
>> +               gcc_jit_function_get_param_count (gcc_jit_function *func)
>> +
>> +   Get the number of parameters of the function.
>> +
>> +.. function::  gcc_jit_type \*
>> +               gcc_jit_function_get_return_type (gcc_jit_function *func)
>> +
>> +   Get the return type of the function.
>> +
>
>The documentation part of the patch is incomplete: it hasn't been
>updated to add all the new entrypoints.
>Also, the return type of gcc_jit_function_get_param_count is
>inconsistent (size_t above, but ssize_t below).
>
>
>> diff --git a/gcc/jit/jit-recording.h b/gcc/jit/jit-recording.h
>> index 30e37aff387..525b8bc921d 100644
>> --- a/gcc/jit/jit-recording.h
>> +++ b/gcc/jit/jit-recording.h
>> @@ -538,7 +538,9 @@ public:
>>    virtual bool is_bool () const = 0;
>>    virtual type *is_pointer () = 0;
>>    virtual type *is_array () = 0;
>> +  virtual struct_ *is_struct () { return NULL; }
>
>Can't you use dyn_cast_struct for this?
>Or is this about looking through decorated_type? e.g. for const and
>volatile variants?
>
>I guess my question is, what is the purpose of gcc_jit_type_is_struct?
>
>>    virtual bool is_void () const { return false; }
>> +  virtual vector_type *is_vector () { return NULL; }
>
>Likewise, can't you use dyn_cast_vector_type for this?
>
>>    virtual bool has_known_size () const { return true; }
>>
>>    bool is_numeric () const
>> @@ -595,6 +597,8 @@ public:
>>    bool is_bool () const FINAL OVERRIDE;
>>    type *is_pointer () FINAL OVERRIDE { return dereference (); }
>>    type *is_array () FINAL OVERRIDE { return NULL; }
>> +  vector_type *is_vector () FINAL OVERRIDE { return NULL; }
>> +  struct_ *is_struct () FINAL OVERRIDE { return NULL; }
>
>Likewise, and this is redundant, as it's merely copying the base class
>implementation.
>
>>    bool is_void () const FINAL OVERRIDE { return m_kind == GCC_JIT_TYPE_VOID; }
>>
>>  public:
>> @@ -629,6 +633,8 @@ public:
>>    bool is_bool () const FINAL OVERRIDE { return false; }
>>    type *is_pointer () FINAL OVERRIDE { return m_other_type; }
>>    type *is_array () FINAL OVERRIDE { return NULL; }
>> +  vector_type *is_vector () FINAL OVERRIDE { return NULL; }
>> +  struct_ *is_struct () FINAL OVERRIDE { return NULL; }
>
>Likewise.
>
>
>> @@ -655,6 +661,7 @@ public:
>>    bool is_bool () const FINAL OVERRIDE { return m_other_type->is_bool (); }
>>    type *is_pointer () FINAL OVERRIDE { return m_other_type->is_pointer (); }
>>    type *is_array () FINAL OVERRIDE { return m_other_type->is_array (); }
>> +  struct_ *is_struct () FINAL OVERRIDE { return m_other_type->is_struct (); }
>
>Aha: with a decorated type you look through the decoration.
>
>>  protected:
>>    type *m_other_type;
>> @@ -737,6 +744,8 @@ public:
>>
>>    void replay_into (replayer *) FINAL OVERRIDE;
>>
>> +  vector_type *is_vector () FINAL OVERRIDE { return this; }
>> +
>>  private:
>>    string * make_debug_string () FINAL OVERRIDE;
>>    void write_reproducer (reproducer &r) FINAL OVERRIDE;
>> @@ -765,6 +774,8 @@ class array_type : public type
>>    bool is_bool () const FINAL OVERRIDE { return false; }
>>    type *is_pointer () FINAL OVERRIDE { return NULL; }
>>    type *is_array () FINAL OVERRIDE { return m_element_type; }
>> +  vector_type *is_vector () FINAL OVERRIDE { return NULL; }
>> +  struct_ *is_struct () FINAL OVERRIDE { return NULL; }
>
>Are these redundant?
>
>>    int num_elements () { return m_num_elements; }
>>
>>    void replay_into (replayer *) FINAL OVERRIDE;
>> @@ -799,6 +810,8 @@ public:
>>    bool is_bool () const FINAL OVERRIDE { return false; }
>>    type *is_pointer () FINAL OVERRIDE { return NULL; }
>>    type *is_array () FINAL OVERRIDE { return NULL; }
>> +  vector_type *is_vector () FINAL OVERRIDE { return NULL; }
>> +  struct_ *is_struct () FINAL OVERRIDE { return NULL; }
>
>Likewise.
>
>>    void replay_into (replayer *) FINAL OVERRIDE;
>>
>> @@ -912,6 +925,7 @@ public:
>>    bool is_bool () const FINAL OVERRIDE { return false; }
>>    type *is_pointer () FINAL OVERRIDE { return NULL; }
>>    type *is_array () FINAL OVERRIDE { return NULL; }
>> +  vector_type *is_vector () FINAL OVERRIDE { return NULL; }
>
>Likewise.
>
>>    bool has_known_size () const FINAL OVERRIDE { return m_fields != NULL; }
>>
>> @@ -943,6 +957,8 @@ public:
>>
>>    const char *access_as_type (reproducer &r) FINAL OVERRIDE;
>>
>> +  struct_ *is_struct () FINAL OVERRIDE { return this; }
>> +
>>  private:
>>    string * make_debug_string () FINAL OVERRIDE;
>>    void write_reproducer (reproducer &r) FINAL OVERRIDE;
>> diff --git a/gcc/jit/libgccjit.c b/gcc/jit/libgccjit.c
>> index a00aefc7108..8e6a9e85ff0 100644
>> --- a/gcc/jit/libgccjit.c
>> +++ b/gcc/jit/libgccjit.c
>> @@ -21,6 +21,7 @@ along with GCC; see the file COPYING3.  If not see
>>  #include "config.h"
>>  #include "system.h"
>>  #include "coretypes.h"
>> +#include "tm.h"
>
>Why is this included?  It's not mentioned in the ChangeLog.
>
>>  #include "timevar.h"
>>  #include "typed-splay-tree.h"
>>  #include "cppbuiltin.h"
>> @@ -60,6 +61,14 @@ struct gcc_jit_struct : public gcc::jit::recording::struct_
>>  {
>>  };
>>
>> +struct gcc_jit_function_type : public gcc::jit::recording::function_type
>> +{
>> +};
>> +
>> +struct gcc_jit_vector_type : public gcc::jit::recording::vector_type
>> +{
>> +};
>> +
>
>FWIW these aren't mentioned in the ChangeLog either.
>
>>  struct gcc_jit_field : public gcc::jit::recording::field
>>  {
>>  };
>> @@ -510,6 +519,197 @@ gcc_jit_type_get_volatile (gcc_jit_type *type)
>
>[...]
>
>> +/* Public entrypoint.  See description in libgccjit.h.
>> +
>> +   After error-checking, the real work is done by the
>> +   gcc::jit::recording::function_type::get_param_types method, in
>> +   jit-recording.c.  */
>> +
>> +gcc_jit_type *
>> +gcc_jit_function_type_get_param_type (gcc_jit_function_type *function_type,
>> +				int index)
>> +{
>> +  RETURN_NULL_IF_FAIL (function_type, NULL, NULL, "NULL struct_type");
>> +  int num_params = function_type->get_param_types ().length ();
>> +  gcc::jit::recording::context *ctxt = function_type->m_ctxt;
>
>Should check that index >= 0 as well (or make it unsigned).
>
>Given that gcc_jit_function_get_param_count returns ssize_t, should
>that be the type of "index"?
>
>> +  RETURN_NULL_IF_FAIL_PRINTF3 (index < num_params,
>> +			       ctxt, NULL,
>> +			       "index of %d is too large (%s has %d params)",
>> +			       index,
>> +			       function_type->get_debug_string (),
>> +			       num_params);
>> +  return (gcc_jit_type *)function_type->get_param_types ()[index];
>> +}
>
>[...]
>
>> +extern gcc_jit_field *
>> +gcc_jit_struct_get_field (gcc_jit_struct *struct_type,
>> +			   int index)
>> +{
>> +  RETURN_NULL_IF_FAIL (struct_type, NULL, NULL, "NULL struct type");
>
>Similar comments as per gcc_jit_function_type_get_param_type above.
>Should check here that index is in range (>=0 and < num fields).
>
>> +  return (gcc_jit_field *)struct_type->get_fields ()->get_field (index);
>> +}
>> +
>> +/* Public entrypoint.  See description in libgccjit.h.
>> +
>> +   After error-checking, this calls the trivial
>> +   gcc::jit::recording::struct_::get_fields method in
>> +   jit-recording.h.  */
>> +
>> +ssize_t
>> +gcc_jit_struct_get_field_count (gcc_jit_struct *struct_type)
>> +{
>> +  RETURN_VAL_IF_FAIL (struct_type, -1, NULL, NULL, "NULL struct type");
>> +  return struct_type->get_fields ()->length ();
>> +}
>> +
>
>[...]
>
>> diff --git a/gcc/jit/libgccjit.h b/gcc/jit/libgccjit.h
>> index 7134841bb07..6056d00a3ea 100644
>> --- a/gcc/jit/libgccjit.h
>> +++ b/gcc/jit/libgccjit.h
>> @@ -96,6 +96,12 @@ typedef struct gcc_jit_field gcc_jit_field;
>>     the layout for, or an opaque type.  */
>>  typedef struct gcc_jit_struct gcc_jit_struct;
>>
>> +/* A gcc_jit_function_type encapsulates a function type.  */
>> +typedef struct gcc_jit_function_type gcc_jit_function_type;
>> +
>> +/* A gcc_jit_vector_type encapsulates a vector type.  */
>> +typedef struct gcc_jit_vector_type gcc_jit_vector_type;
>> +
>>  /* A gcc_jit_function encapsulates a function: either one that you're
>>     creating yourself, or a reference to one that you're dynamically
>>     linking to within the rest of the process.  */
>> @@ -586,6 +592,61 @@ gcc_jit_type_get_const (gcc_jit_type *type);
>>  extern gcc_jit_type *
>>  gcc_jit_type_get_volatile (gcc_jit_type *type);
>>
>> +/* Given type "T", return TRUE if the type is an array.  */
>> +extern gcc_jit_type *
>> +gcc_jit_type_is_array (gcc_jit_type *type);
>
>The comment is unclear; does this actually return the type vs NULL?
>
>As noted above, I think we need to think about what happens on
>qualified types; is stripping them the responsibility of the caller?
>Should it be?  (I'm thinking "yes", but presumably all this is
>motivated by your rust hacking).
>
>Also, there isn't a type "T" here; the param name is "type", and there
>isn't a supporting example using "T" as a placeholder.
>Maybe just lose the 'Given type "T", ' prefix here and below (unless
>giving a example).
>
>> +/* Given type "T", return TRUE if the type is a bool.  */
>> +extern int
>> +gcc_jit_type_is_bool (gcc_jit_type *type);
>
>I'd prefer "return non-zero" over "return TRUE" (here, and in various
>places below).
>
>Does this check for the "bool" type i.e.:
>  /* C++'s bool type; also C99's "_Bool" type, aka "bool" if using
>     stdbool.h.  */
>  GCC_JIT_TYPE_BOOL,
>?
>
>> +/* Given type "T", return the function type if it is one.  */
>
>..."or NULL".
>
>> +extern gcc_jit_function_type *
>> +gcc_jit_type_is_function_ptr_type (gcc_jit_type *type);
>> +
>> +/* Given a function type, return its return type.  */
>> +extern gcc_jit_type *
>> +gcc_jit_function_type_get_return_type (gcc_jit_function_type *function_type);
>> +
>> +/* Given a function type, return its number of parameters.  */
>> +extern ssize_t
>> +gcc_jit_function_type_get_param_count (gcc_jit_function_type *function_type);
>> +
>> +/* Given a function type, return the type of the specified parameter.  */
>> +extern gcc_jit_type *
>> +gcc_jit_function_type_get_param_type (gcc_jit_function_type *function_type,
>> +				int index);
>> +
>> +/* Given type "T", return the type pointed by the pointer type
>> + * or NULL if it's not a pointer.  */
>> +extern gcc_jit_type *
>> +gcc_jit_type_is_pointer (gcc_jit_type *type);
>> +
>> +/* Given type "T", return TRUE if the type is an int.  */
>> +extern int
>> +gcc_jit_type_is_int (gcc_jit_type *type);
>
>I'm not sure I understand what this function does, which suggests it's
>misnamed.  The current name suggests that it checks for the C "int"
>type, whereas I believe it actually checks for an integral
>type.  Should it be:
>
>extern int
>gcc_jit_type_is_integral (gcc_jit_type *type);
>
>?
>
>What's the output?  Do you merely need nonzero/zero for boolean, or
>information on the width of the type/signedness, or whatnot?  (perhaps
>have some out params for extracting width/signedness for when it
>returns nonzero?)
>
>Looking at the testcase, it looks like it currently returns false on
>the _Bool type.  Is that correct?
>
>
>> +/* Given type "T", return the unqualified type, i.e. for a
>> + * decorated type, return the type it wraps.  */
>> +extern gcc_jit_type *
>> +gcc_jit_type_unqualified (gcc_jit_type *type);
>
>"decorated" is a term used inside the implementation, but not in the
>user-facing docs.
>
>How about:
>
>  /* Given a type, return the unqualified type, removing "const",
>"volatile"
>     and alignment qualifiers.  */
>
>or somesuch.
>
>> +/* Given type "T", return TRUE if the type is a vector type.  */
>> +extern gcc_jit_vector_type *
>> +gcc_jit_type_is_vector (gcc_jit_type *type);
>
>As above, this doesn't return TRUE, it's more of a dynamic cast.
>Likewise about responsibility for qualifiers.
>
>> +/* Given type "T", return the struct type or NULL.  */
>> +extern gcc_jit_struct *
>> +gcc_jit_type_is_struct (gcc_jit_type *type);
>
>Wording could be improved as noted above.
>
>> +/* Given a vector type, return the number of units it contains.  */
>> +extern ssize_t
>> +gcc_jit_vector_type_get_num_units (gcc_jit_vector_type *vector_type);
>> +
>> +/* Given a vector type, return the type of its elements.  */
>> +extern gcc_jit_type *
>> +gcc_jit_vector_type_get_element_type (gcc_jit_vector_type *vector_type);
>> +
>
>[...]
>
>> @@ -647,6 +708,15 @@ gcc_jit_struct_set_fields (gcc_jit_struct *struct_type,
>>  			   int num_fields,
>>  			   gcc_jit_field **fields);
>>
>> +/* Get a field by index.  */
>> +extern gcc_jit_field *
>> +gcc_jit_struct_get_field (gcc_jit_struct *struct_type,
>> +			   int index);
>> +
>> +/* Get the number of fields.  */
>> +extern ssize_t
>> +gcc_jit_struct_get_field_count (gcc_jit_struct *struct_type);
>
>Do we need these for unions?  Or skip them for now?
>
>> @@ -740,6 +810,14 @@ gcc_jit_function_as_object (gcc_jit_function *func);
>>  extern gcc_jit_param *
>>  gcc_jit_function_get_param (gcc_jit_function *func, int index);
>>
>> +/* Get the number of params of a function.  */
>> +extern ssize_t
>> +gcc_jit_function_get_param_count (gcc_jit_function *func);
>> +
>> +/* Get the return type of a function.  */
>> +extern gcc_jit_type *
>> +gcc_jit_function_get_return_type (gcc_jit_function *func);
>
>Are these redundant if there's a way to ask a gcc_jit_function for its
>type, and then to use the gcc_jit_function_type_ functions?
>(I don't mind if they are)
>
>> @@ -1518,6 +1596,47 @@ gcc_jit_version_minor (void);
>>  extern int
>>  gcc_jit_version_patchlevel (void);
>>
>> +#define LIBGCCJIT_HAVE_gcc_jit_function_reflection
>> +
>> +/* Reflection functions to get the number of parameters, return type of
>> +   a function and whether a type is a bool from the C API.
>> +
>> +   This API entrypoint was added in LIBGCCJIT_ABI_15; you can test for its
>> +   presence using
>> +     #ifdef LIBGCCJIT_HAVE_gcc_jit_function_reflection
>> +*/
>
>This has become a big mixture of things beyond just function
>reflection, so I think I'd prefer it if each entrypoint "funcname" had
>its own "LIBGCCJIT_HAVE_funcname" define.  Or just "REFLECTION" rather
>than "function_reflection", that's probably simpler.
>Note that the existing "HAVE_foo" defines are lowercase "foo" when it's
>an actual entrypoint named "foo", and are uppercase otherwise e.g.
>LIBGCCJIT_HAVE_SWITCH_STATEMENTS and LIBGCCJIT_HAVE_TIMING_API.
>
>> +extern gcc_jit_type *
>> +gcc_jit_function_get_return_type (gcc_jit_function *func);
>> +extern ssize_t
>> +gcc_jit_function_get_param_count (gcc_jit_function *func);
>> +extern gcc_jit_type *
>> +gcc_jit_type_is_array (gcc_jit_type *type);
>> +extern int
>> +gcc_jit_type_is_bool (gcc_jit_type *type);
>> +extern gcc_jit_function_type *
>> +gcc_jit_type_is_function_ptr_type (gcc_jit_type *type);
>> +extern gcc_jit_type *
>> +gcc_jit_function_type_get_return_type (gcc_jit_function_type *function_type);
>> +extern ssize_t
>> +gcc_jit_function_type_get_param_count (gcc_jit_function_type *function_type);
>> +extern gcc_jit_type *
>> +gcc_jit_function_type_get_param_type (gcc_jit_function_type *function_type,
>> +				int index);
>> +extern int
>> +gcc_jit_type_is_int (gcc_jit_type *type);
>> +extern gcc_jit_type *
>> +gcc_jit_type_is_pointer (gcc_jit_type *type);
>> +extern gcc_jit_vector_type *
>> +gcc_jit_type_is_vector (gcc_jit_type *type);
>> +extern gcc_jit_struct *
>> +gcc_jit_type_is_struct (gcc_jit_type *type);
>> +extern ssize_t
>> +gcc_jit_vector_type_get_num_units (gcc_jit_vector_type *vector_type);
>> +extern gcc_jit_type *
>> +gcc_jit_vector_type_get_element_type (gcc_jit_vector_type *vector_type);
>> +extern gcc_jit_type *
>> +gcc_jit_type_unqualified (gcc_jit_type *type);
>
>Is this part of the patch a duplicate copy of the various things added
>above?  Perhaps copy-and-paste error, or am I misreading this?
>
>[...]
>
>Hope this is constructive
>Dave
>

[-- Attachment #2: 0001-This-patch-add-some-reflection-functions-in-the-jit-.patch --]
[-- Type: text/plain, Size: 25133 bytes --]

From a9409a119adf55ab9989de700266702ca78e8da5 Mon Sep 17 00:00:00 2001
From: Antoni Boucher <bouanto@zoho.com>
Date: Sat, 1 Aug 2020 17:52:17 -0400
Subject: [PATCH] This patch add some reflection functions in the jit C api
 [PR96889]

2020-09-1  Antoni Boucher  <bouanto@zoho.com>

    gcc/jit/
            PR target/96889
            * docs/topics/compatibility.rst (LIBGCCJIT_ABI_15): New ABI tag.
            * docs/topics/functions.rst: Add documentation for the
            functions gcc_jit_function_get_return_type and
            gcc_jit_function_get_param_count
            * libgccjit.c:
            (gcc_jit_function_get_return_type, gcc_jit_function_get_param_count,
            gcc_jit_function_type_get_return_type,
            gcc_jit_function_type_get_param_count,
            gcc_jit_function_type_get_param_type, gcc_jit_type_unqualified,
            gcc_jit_type_is_array, gcc_jit_type_is_bool,
            gcc_jit_type_is_function_ptr_type, gcc_jit_type_is_int,
            gcc_jit_type_is_pointer, gcc_jit_type_is_vector,
            gcc_jit_vector_type_get_element_type,
            gcc_jit_vector_type_get_num_units, gcc_jit_struct_get_field,
            gcc_jit_type_is_struct, gcc_jit_struct_get_field_count): New
            functions.
            (struct gcc_jit_function_type, struct gcc_jit_vector_type):
            New types.
            * libgccjit.h:
            (gcc_jit_function_get_return_type, gcc_jit_function_get_param_count,
            gcc_jit_function_type_get_return_type,
            gcc_jit_function_type_get_param_count,
            gcc_jit_function_type_get_param_type, gcc_jit_type_unqualified,
            gcc_jit_type_is_array, gcc_jit_type_is_bool,
            gcc_jit_type_is_function_ptr_type, gcc_jit_type_is_int,
            gcc_jit_type_is_pointer, gcc_jit_type_is_vector,
            gcc_jit_vector_type_get_element_type,
            gcc_jit_vector_type_get_num_units, gcc_jit_struct_get_field,
            gcc_jit_type_is_struct, gcc_jit_struct_get_field_count): New
            function declarations.
            (struct gcc_jit_function_type, struct gcc_jit_vector_type):
            New types.
            * jit-recording.h: New functions (is_struct and is_vector)
            * libgccjit.map (LIBGCCJIT_ABI_15): New ABI tag.

    gcc/testsuite/
            PR target/96889
            * jit.dg/all-non-failing-tests.h: Add test-reflection.c.
            * jit.dg/test-reflection.c: New test.
---
 gcc/jit/docs/topics/compatibility.rst        |  41 +++
 gcc/jit/docs/topics/functions.rst            |  10 +
 gcc/jit/jit-recording.h                      |   7 +
 gcc/jit/libgccjit.c                          | 258 +++++++++++++++++++
 gcc/jit/libgccjit.h                          |  87 +++++++
 gcc/jit/libgccjit.map                        |  21 ++
 gcc/testsuite/jit.dg/all-non-failing-tests.h |  10 +
 gcc/testsuite/jit.dg/test-reflection.c       |  89 +++++++
 8 files changed, 523 insertions(+)
 create mode 100644 gcc/testsuite/jit.dg/test-reflection.c

diff --git a/gcc/jit/docs/topics/compatibility.rst b/gcc/jit/docs/topics/compatibility.rst
index 6bfa101ed71..236e5c72d81 100644
--- a/gcc/jit/docs/topics/compatibility.rst
+++ b/gcc/jit/docs/topics/compatibility.rst
@@ -226,3 +226,44 @@ entrypoints:
 --------------------
 ``LIBGCCJIT_ABI_14`` covers the addition of
 :func:`gcc_jit_global_set_initializer`
+
+.. _LIBGCCJIT_ABI_15:
+
+``LIBGCCJIT_ABI_15``
+--------------------
+``LIBGCCJIT_ABI_15`` covers the addition of reflection functions via API
+entrypoints:
+
+  * :func:`gcc_jit_function_get_return_type`
+
+  * :func:`gcc_jit_function_get_param_count`
+
+  * :func:`gcc_jit_type_is_array`
+
+  * :func:`gcc_jit_type_is_bool`
+
+  * :func:`gcc_jit_type_is_integral`
+
+  * :func:`gcc_jit_type_is_pointer`
+
+  * :func:`gcc_jit_type_is_struct`
+
+  * :func:`gcc_jit_type_is_vector`
+
+  * :func:`gcc_jit_type_unqualified`
+
+  * :func:`gcc_jit_type_is_function_ptr_type`
+
+  * :func:`gcc_jit_function_type_get_return_type`
+
+  * :func:`gcc_jit_function_type_get_param_count`
+
+  * :func:`gcc_jit_function_type_get_param_type`
+
+  * :func:`gcc_jit_vector_type_get_num_units`
+
+  * :func:`gcc_jit_vector_type_get_element_type`
+
+  * :func:`gcc_jit_struct_get_field`
+
+  * :func:`gcc_jit_struct_get_field_count`
diff --git a/gcc/jit/docs/topics/functions.rst b/gcc/jit/docs/topics/functions.rst
index eb40d64010e..aa6de87282d 100644
--- a/gcc/jit/docs/topics/functions.rst
+++ b/gcc/jit/docs/topics/functions.rst
@@ -171,6 +171,16 @@ Functions
    underlying string, so it is valid to pass in a pointer to an on-stack
    buffer.
 
+.. function::  ssize_t \
+               gcc_jit_function_get_param_count (gcc_jit_function *func)
+
+   Get the number of parameters of the function.
+
+.. function::  gcc_jit_type \*
+               gcc_jit_function_get_return_type (gcc_jit_function *func)
+
+   Get the return type of the function.
+
 Blocks
 ------
 .. type:: gcc_jit_block
diff --git a/gcc/jit/jit-recording.h b/gcc/jit/jit-recording.h
index 30e37aff387..8f494a060ef 100644
--- a/gcc/jit/jit-recording.h
+++ b/gcc/jit/jit-recording.h
@@ -538,7 +538,9 @@ public:
   virtual bool is_bool () const = 0;
   virtual type *is_pointer () = 0;
   virtual type *is_array () = 0;
+  virtual struct_ *is_struct () { return NULL; }
   virtual bool is_void () const { return false; }
+  virtual vector_type *is_vector () { return NULL; }
   virtual bool has_known_size () const { return true; }
 
   bool is_numeric () const
@@ -655,6 +657,7 @@ public:
   bool is_bool () const FINAL OVERRIDE { return m_other_type->is_bool (); }
   type *is_pointer () FINAL OVERRIDE { return m_other_type->is_pointer (); }
   type *is_array () FINAL OVERRIDE { return m_other_type->is_array (); }
+  struct_ *is_struct () FINAL OVERRIDE { return m_other_type->is_struct (); }
 
 protected:
   type *m_other_type;
@@ -737,6 +740,8 @@ public:
 
   void replay_into (replayer *) FINAL OVERRIDE;
 
+  vector_type *is_vector () FINAL OVERRIDE { return this; }
+
 private:
   string * make_debug_string () FINAL OVERRIDE;
   void write_reproducer (reproducer &r) FINAL OVERRIDE;
@@ -943,6 +948,8 @@ public:
 
   const char *access_as_type (reproducer &r) FINAL OVERRIDE;
 
+  struct_ *is_struct () FINAL OVERRIDE { return this; }
+
 private:
   string * make_debug_string () FINAL OVERRIDE;
   void write_reproducer (reproducer &r) FINAL OVERRIDE;
diff --git a/gcc/jit/libgccjit.c b/gcc/jit/libgccjit.c
index a00aefc7108..406c62beb55 100644
--- a/gcc/jit/libgccjit.c
+++ b/gcc/jit/libgccjit.c
@@ -60,6 +60,14 @@ struct gcc_jit_struct : public gcc::jit::recording::struct_
 {
 };
 
+struct gcc_jit_function_type : public gcc::jit::recording::function_type
+{
+};
+
+struct gcc_jit_vector_type : public gcc::jit::recording::vector_type
+{
+};
+
 struct gcc_jit_field : public gcc::jit::recording::field
 {
 };
@@ -510,6 +518,197 @@ gcc_jit_type_get_volatile (gcc_jit_type *type)
   return (gcc_jit_type *)type->get_volatile ();
 }
 
+/* Public entrypoint.  See description in libgccjit.h.
+
+   After error-checking, the real work is done by the
+   gcc::jit::recording::type::is_array method, in
+   jit-recording.c.  */
+
+gcc_jit_type *
+gcc_jit_type_is_array (gcc_jit_type *type)
+{
+  RETURN_NULL_IF_FAIL (type, NULL, NULL, "NULL type");
+
+  return (gcc_jit_type *)type->is_array ();
+}
+
+/* Public entrypoint.  See description in libgccjit.h.
+
+   After error-checking, the real work is done by the
+   gcc::jit::recording::type::is_bool method, in
+   jit-recording.c.  */
+
+int
+gcc_jit_type_is_bool (gcc_jit_type *type)
+{
+  RETURN_VAL_IF_FAIL (type, FALSE, NULL, NULL, "NULL type");
+
+  return type->is_bool ();
+}
+
+/* Public entrypoint.  See description in libgccjit.h.
+
+   After error-checking, the real work is done by the
+   gcc::jit::recording::type::is_pointer method, in
+   jit-recording.c.  */
+
+gcc_jit_type *
+gcc_jit_type_is_pointer (gcc_jit_type *type)
+{
+  RETURN_NULL_IF_FAIL (type, NULL, NULL, "NULL type");
+
+  return (gcc_jit_type *)type->is_pointer ();
+}
+
+/* Public entrypoint.  See description in libgccjit.h.
+
+   After error-checking, the real work is done by the
+   gcc::jit::recording::type::is_int method, in
+   jit-recording.c.  */
+
+int
+gcc_jit_type_is_integral (gcc_jit_type *type)
+{
+  RETURN_VAL_IF_FAIL (type, FALSE, NULL, NULL, "NULL type");
+
+  return type->is_int ();
+}
+
+/* Public entrypoint.  See description in libgccjit.h.
+
+   After error-checking, the real work is done by the
+   gcc::jit::recording::type::is_vector method, in
+   jit-recording.c.  */
+
+gcc_jit_vector_type *
+gcc_jit_type_is_vector (gcc_jit_type *type)
+{
+  RETURN_NULL_IF_FAIL (type, NULL, NULL, "NULL type");
+  gcc::jit::recording::vector_type *vector_type = type->is_vector ();
+  return (gcc_jit_vector_type *)vector_type;
+}
+
+/* Public entrypoint.  See description in libgccjit.h.
+
+   After error-checking, the real work is done by the
+   gcc::jit::recording::type::is_struct method, in
+   jit-recording.c.  */
+
+gcc_jit_struct *
+gcc_jit_type_is_struct (gcc_jit_type *type)
+{
+  RETURN_NULL_IF_FAIL (type, NULL, NULL, "NULL type");
+  gcc::jit::recording::struct_ *struct_type = type->is_struct ();
+  return (gcc_jit_struct *)struct_type;
+}
+
+/* Public entrypoint.  See description in libgccjit.h.
+
+   After error-checking, the real work is done by the
+   gcc::jit::recording::vector_type::get_num_units method, in
+   jit-recording.c.  */
+
+ssize_t
+gcc_jit_vector_type_get_num_units (gcc_jit_vector_type *vector_type)
+{
+  RETURN_VAL_IF_FAIL (vector_type, -1, NULL, NULL, "NULL vector_type");
+  return vector_type->get_num_units ();
+}
+
+/* Public entrypoint.  See description in libgccjit.h.
+
+   After error-checking, the real work is done by the
+   gcc::jit::recording::vector_type::get_element_type method, in
+   jit-recording.c.  */
+
+gcc_jit_type *
+gcc_jit_vector_type_get_element_type (gcc_jit_vector_type *vector_type)
+{
+  RETURN_NULL_IF_FAIL (vector_type, NULL, NULL, "NULL vector_type");
+  return (gcc_jit_type *)vector_type->get_element_type ();
+}
+
+/* Public entrypoint.  See description in libgccjit.h.
+
+   After error-checking, the real work is done by the
+   gcc::jit::recording::type::unqualified method, in
+   jit-recording.c.  */
+
+gcc_jit_type *
+gcc_jit_type_unqualified (gcc_jit_type *type)
+{
+  RETURN_NULL_IF_FAIL (type, NULL, NULL, "NULL type");
+
+  return (gcc_jit_type *)type->unqualified ();
+}
+
+/* Public entrypoint.  See description in libgccjit.h.
+
+   After error-checking, the real work is done by the
+   gcc::jit::recording::type::dyn_cast_function_type method, in
+   jit-recording.c.  */
+
+gcc_jit_function_type *
+gcc_jit_type_is_function_ptr_type (gcc_jit_type *type)
+{
+  RETURN_NULL_IF_FAIL (type, NULL, NULL, "NULL type");
+  gcc::jit::recording::type *func_ptr_type = type->dereference ();
+  RETURN_NULL_IF_FAIL (func_ptr_type, NULL, NULL, "NULL type");
+  gcc::jit::recording::function_type *func_type =
+    func_ptr_type->dyn_cast_function_type ();
+  RETURN_NULL_IF_FAIL (func_type, NULL, NULL, "NULL type");
+
+  return (gcc_jit_function_type *)func_type;
+}
+
+/* Public entrypoint.  See description in libgccjit.h.
+
+   After error-checking, the real work is done by the
+   gcc::jit::recording::function_type::get_return_type method, in
+   jit-recording.c.  */
+
+gcc_jit_type *
+gcc_jit_function_type_get_return_type (gcc_jit_function_type *function_type)
+{
+  RETURN_NULL_IF_FAIL (function_type, NULL, NULL, "NULL struct_type");
+  return (gcc_jit_type *)function_type->get_return_type ();
+}
+
+/* Public entrypoint.  See description in libgccjit.h.
+
+   After error-checking, the real work is done by the
+   gcc::jit::recording::function_type::get_param_types method, in
+   jit-recording.c.  */
+
+ssize_t
+gcc_jit_function_type_get_param_count (gcc_jit_function_type *function_type)
+{
+  RETURN_VAL_IF_FAIL (function_type, -1, NULL, NULL, "NULL struct_type");
+  return function_type->get_param_types ().length ();
+}
+
+/* Public entrypoint.  See description in libgccjit.h.
+
+   After error-checking, the real work is done by the
+   gcc::jit::recording::function_type::get_param_types method, in
+   jit-recording.c.  */
+
+gcc_jit_type *
+gcc_jit_function_type_get_param_type (gcc_jit_function_type *function_type,
+				int index)
+{
+  RETURN_NULL_IF_FAIL (function_type, NULL, NULL, "NULL struct_type");
+  int num_params = function_type->get_param_types ().length ();
+  gcc::jit::recording::context *ctxt = function_type->m_ctxt;
+  RETURN_NULL_IF_FAIL_PRINTF3 (index < num_params,
+			       ctxt, NULL,
+			       "index of %d is too large (%s has %d params)",
+			       index,
+			       function_type->get_debug_string (),
+			       num_params);
+  return (gcc_jit_type *)function_type->get_param_types ()[index];
+}
+
 /* Public entrypoint.  See description in libgccjit.h.
 
    After error-checking, the real work is done by the
@@ -731,6 +930,36 @@ gcc_jit_struct_set_fields (gcc_jit_struct *struct_type,
 			   (gcc::jit::recording::field **)fields);
 }
 
+
+/* Public entrypoint.  See description in libgccjit.h.
+
+   After error-checking, the real work is done by the
+   gcc::jit::recording::fields::get_field method in
+   jit-recording.c.  */
+extern gcc_jit_field *
+gcc_jit_struct_get_field (gcc_jit_struct *struct_type,
+			   int index)
+{
+  RETURN_NULL_IF_FAIL (struct_type, NULL, NULL, "NULL struct type");
+  RETURN_NULL_IF_FAIL (struct_type->get_fields (), NULL, NULL, "NULL struct fields");
+  RETURN_NULL_IF_FAIL (index < struct_type->get_fields ()->length (), NULL,
+				NULL, "NULL struct type");
+  return (gcc_jit_field *)struct_type->get_fields ()->get_field (index);
+}
+
+/* Public entrypoint.  See description in libgccjit.h.
+
+   After error-checking, this calls the trivial
+   gcc::jit::recording::struct_::get_fields method in
+   jit-recording.h.  */
+
+ssize_t
+gcc_jit_struct_get_field_count (gcc_jit_struct *struct_type)
+{
+  RETURN_VAL_IF_FAIL (struct_type, -1, NULL, NULL, "NULL struct type");
+  return struct_type->get_fields ()->length ();
+}
+
 /* Public entrypoint.  See description in libgccjit.h.
 
    After error-checking, the real work is done by the
@@ -1012,6 +1241,35 @@ gcc_jit_function_get_param (gcc_jit_function *func, int index)
   return static_cast <gcc_jit_param *> (func->get_param (index));
 }
 
+/* Public entrypoint.  See description in libgccjit.h.
+
+   After error-checking, the real work is done by the
+   gcc::jit::recording::function::get_params method, in
+   jit-recording.h.
+  */
+
+ssize_t
+gcc_jit_function_get_param_count (gcc_jit_function *func)
+{
+  RETURN_VAL_IF_FAIL (func, -1, NULL, NULL, "NULL function");
+  gcc::jit::recording::context *ctxt = func->m_ctxt;
+  JIT_LOG_FUNC (ctxt->get_logger ());
+  return func->get_params ().length ();
+}
+
+/* Public entrypoint.  See description in libgccjit.h.
+
+   After error-checking, the real work is done by the
+   gcc::jit::recording::function::get_return_type method, in
+   jit-recording.h.  */
+
+gcc_jit_type *
+gcc_jit_function_get_return_type (gcc_jit_function *func)
+{
+    RETURN_NULL_IF_FAIL (func, NULL, NULL, "NULL function");
+    return (gcc_jit_type *)func->get_return_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 7134841bb07..db4ccffb41c 100644
--- a/gcc/jit/libgccjit.h
+++ b/gcc/jit/libgccjit.h
@@ -96,6 +96,12 @@ typedef struct gcc_jit_field gcc_jit_field;
    the layout for, or an opaque type.  */
 typedef struct gcc_jit_struct gcc_jit_struct;
 
+/* A gcc_jit_function_type encapsulates a function type.  */
+typedef struct gcc_jit_function_type gcc_jit_function_type;
+
+/* A gcc_jit_vector_type encapsulates a vector type.  */
+typedef struct gcc_jit_vector_type gcc_jit_vector_type;
+
 /* A gcc_jit_function encapsulates a function: either one that you're
    creating yourself, or a reference to one that you're dynamically
    linking to within the rest of the process.  */
@@ -647,6 +653,15 @@ gcc_jit_struct_set_fields (gcc_jit_struct *struct_type,
 			   int num_fields,
 			   gcc_jit_field **fields);
 
+/* Get a field by index.  */
+extern gcc_jit_field *
+gcc_jit_struct_get_field (gcc_jit_struct *struct_type,
+			   int index);
+
+/* Get the number of fields.  */
+extern ssize_t
+gcc_jit_struct_get_field_count (gcc_jit_struct *struct_type);
+
 /* Unions work similarly to structs.  */
 extern gcc_jit_type *
 gcc_jit_context_new_union_type (gcc_jit_context *ctxt,
@@ -1518,6 +1533,78 @@ gcc_jit_version_minor (void);
 extern int
 gcc_jit_version_patchlevel (void);
 
+#define LIBGCCJIT_HAVE_REFLECTION
+
+/* Reflection functions to get the number of parameters, return type of
+   a function and whether a type is a bool from the C API.
+
+   This API entrypoint was added in LIBGCCJIT_ABI_15; you can test for its
+   presence using
+     #ifdef LIBGCCJIT_HAVE_REFLECTION
+*/
+/* Get the return type of a function.  */
+extern gcc_jit_type *
+gcc_jit_function_get_return_type (gcc_jit_function *func);
+
+/* Get the number of params of a function.  */
+extern ssize_t
+gcc_jit_function_get_param_count (gcc_jit_function *func);
+
+/* Get the element type of an array type or NULL if it's not an array.  */
+extern gcc_jit_type *
+gcc_jit_type_is_array (gcc_jit_type *type);
+
+/* Return non-zero if the type is a bool.  */
+extern int
+gcc_jit_type_is_bool (gcc_jit_type *type);
+
+/* Return the function type if it is one or NULL.  */
+extern gcc_jit_function_type *
+gcc_jit_type_is_function_ptr_type (gcc_jit_type *type);
+
+/* Given a function type, return its return type.  */
+extern gcc_jit_type *
+gcc_jit_function_type_get_return_type (gcc_jit_function_type *function_type);
+
+/* Given a function type, return its number of parameters.  */
+extern ssize_t
+gcc_jit_function_type_get_param_count (gcc_jit_function_type *function_type);
+
+/* Given a function type, return the type of the specified parameter.  */
+extern gcc_jit_type *
+gcc_jit_function_type_get_param_type (gcc_jit_function_type *function_type,
+				int index);
+
+/* Return non-zero if the type is an integral.  */
+extern int
+gcc_jit_type_is_integral (gcc_jit_type *type);
+
+/* Return the type pointed by the pointer type or NULL if it's not a
+ * pointer.  */
+extern gcc_jit_type *
+gcc_jit_type_is_pointer (gcc_jit_type *type);
+
+/* Given a type, return a dynamic cast to a vector type or NULL.  */
+extern gcc_jit_vector_type *
+gcc_jit_type_is_vector (gcc_jit_type *type);
+
+/* Given a type, return a dynamic cast to a struct type or NULL.  */
+extern gcc_jit_struct *
+gcc_jit_type_is_struct (gcc_jit_type *type);
+
+/* Given a vector type, return the number of units it contains.  */
+extern ssize_t
+gcc_jit_vector_type_get_num_units (gcc_jit_vector_type *vector_type);
+
+/* Given a vector type, return the type of its elements.  */
+extern gcc_jit_type *
+gcc_jit_vector_type_get_element_type (gcc_jit_vector_type *vector_type);
+
+/* Given a type, return the unqualified type, removing "const", "volatile"
+ * and alignment qualifiers.  */
+extern gcc_jit_type *
+gcc_jit_type_unqualified (gcc_jit_type *type);
+
 #ifdef __cplusplus
 }
 #endif /* __cplusplus */
diff --git a/gcc/jit/libgccjit.map b/gcc/jit/libgccjit.map
index a6e67e781a4..720b6ca286f 100644
--- a/gcc/jit/libgccjit.map
+++ b/gcc/jit/libgccjit.map
@@ -192,3 +192,24 @@ LIBGCCJIT_ABI_14 {
   global:
     gcc_jit_global_set_initializer;
 } LIBGCCJIT_ABI_13;
+
+LIBGCCJIT_ABI_15 {
+  global:
+    gcc_jit_function_get_return_type;
+    gcc_jit_function_get_param_count;
+    gcc_jit_function_type_get_return_type;
+    gcc_jit_function_type_get_param_count;
+    gcc_jit_function_type_get_param_type;
+    gcc_jit_type_unqualified;
+    gcc_jit_type_is_array;
+    gcc_jit_type_is_bool;
+    gcc_jit_type_is_function_ptr_type;
+    gcc_jit_type_is_integral;
+    gcc_jit_type_is_pointer;
+    gcc_jit_type_is_vector;
+    gcc_jit_vector_type_get_element_type;
+    gcc_jit_vector_type_get_num_units;
+    gcc_jit_struct_get_field;
+    gcc_jit_type_is_struct;
+    gcc_jit_struct_get_field_count;
+} LIBGCCJIT_ABI_14;
diff --git a/gcc/testsuite/jit.dg/all-non-failing-tests.h b/gcc/testsuite/jit.dg/all-non-failing-tests.h
index 4202eb7798b..a269144d2df 100644
--- a/gcc/testsuite/jit.dg/all-non-failing-tests.h
+++ b/gcc/testsuite/jit.dg/all-non-failing-tests.h
@@ -258,6 +258,13 @@
 #undef create_code
 #undef verify_code
 
+/* test-reflection.c */
+#define create_code create_code_reflection
+#define verify_code verify_code_reflection
+#include "test-reflection.c"
+#undef create_code
+#undef verify_code
+
 /* test-string-literal.c */
 #define create_code create_code_string_literal
 #define verify_code verify_code_string_literal
@@ -424,6 +431,9 @@ const struct testcase testcases[] = {
   {"reading_struct ",
    create_code_reading_struct ,
    verify_code_reading_struct },
+  {"reflection",
+   create_code_reflection ,
+   verify_code_reflection },
   {"string_literal",
    create_code_string_literal,
    verify_code_string_literal},
diff --git a/gcc/testsuite/jit.dg/test-reflection.c b/gcc/testsuite/jit.dg/test-reflection.c
new file mode 100644
index 00000000000..b3cf2942f3a
--- /dev/null
+++ b/gcc/testsuite/jit.dg/test-reflection.c
@@ -0,0 +1,89 @@
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "libgccjit.h"
+
+#include "harness.h"
+
+void
+create_code (gcc_jit_context *ctxt, void *user_data)
+{
+  /* Do nothing.  */
+}
+
+void
+verify_code (gcc_jit_context *ctxt, gcc_jit_result *result)
+{
+  /* Get the built-in functions.  */
+  gcc_jit_function *builtin_sin =
+    gcc_jit_context_get_builtin_function (ctxt, "sin");
+
+  CHECK_VALUE (gcc_jit_function_get_param_count(builtin_sin), 1);
+
+  gcc_jit_type *double_type =
+    gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_DOUBLE);
+  CHECK_VALUE (gcc_jit_function_get_return_type(builtin_sin), double_type);
+  CHECK (!gcc_jit_type_is_integral(double_type));
+
+  gcc_jit_type *bool_type =
+    gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_BOOL);
+  CHECK (gcc_jit_type_is_bool(bool_type));
+  CHECK (!gcc_jit_type_is_integral(bool_type));
+
+  gcc_jit_type *aligned_bool_type =
+    gcc_jit_type_get_aligned(gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_BOOL), 8);
+  CHECK (gcc_jit_type_is_bool(aligned_bool_type));
+  CHECK (bool_type != aligned_bool_type);
+  CHECK_VALUE (gcc_jit_type_unqualified(aligned_bool_type), bool_type);
+
+  CHECK_VALUE (gcc_jit_type_unqualified(gcc_jit_type_get_const(bool_type)), bool_type);
+  CHECK_VALUE (gcc_jit_type_unqualified(gcc_jit_type_get_volatile(bool_type)), bool_type);
+
+  gcc_jit_type *int64 =
+    gcc_jit_context_get_int_type(ctxt, 8, 1);
+  CHECK (gcc_jit_type_is_integral(int64));
+  gcc_jit_type *uint64 =
+    gcc_jit_context_get_int_type(ctxt, 8, 0);
+  CHECK (gcc_jit_type_is_integral(uint64));
+  gcc_jit_type *int8 =
+    gcc_jit_context_get_int_type(ctxt, 1, 1);
+  CHECK (gcc_jit_type_is_integral(int8));
+  gcc_jit_type *uint8 =
+    gcc_jit_context_get_int_type(ctxt, 1, 0);
+  CHECK (gcc_jit_type_is_integral(uint8));
+
+  CHECK (!gcc_jit_type_is_vector(double_type));
+  gcc_jit_type *vec_type = gcc_jit_type_get_vector (double_type, 4);
+  gcc_jit_vector_type *vector_type = gcc_jit_type_is_vector(vec_type);
+  CHECK (vector_type);
+  CHECK (vec_type != double_type);
+  CHECK_VALUE (gcc_jit_vector_type_get_element_type(vector_type), double_type);
+  CHECK_VALUE (gcc_jit_vector_type_get_num_units(vector_type), 4);
+
+  CHECK (!gcc_jit_type_is_pointer(double_type));
+  CHECK_VALUE (gcc_jit_type_is_pointer(gcc_jit_type_get_pointer(double_type)), double_type);
+
+  gcc_jit_type* params[2] = {int8, uint64};
+  gcc_jit_type *function_ptr_type = gcc_jit_context_new_function_ptr_type(ctxt, NULL, int64, 2, params, 0);
+  gcc_jit_function_type *function_type = gcc_jit_type_is_function_ptr_type (function_ptr_type);
+  CHECK (function_type);
+  int param_count = gcc_jit_function_type_get_param_count(function_type);
+  CHECK_VALUE (param_count, 2);
+  gcc_jit_type *return_type = gcc_jit_function_type_get_return_type(function_type);
+  CHECK_VALUE (return_type, int64);
+  gcc_jit_type *param1 = gcc_jit_function_type_get_param_type(function_type, 0);
+  CHECK_VALUE (param1, int8);
+  gcc_jit_type *param2 = gcc_jit_function_type_get_param_type(function_type, 1);
+  CHECK_VALUE (param2, uint64);
+
+  gcc_jit_field *field1 = gcc_jit_context_new_field (ctxt, NULL, uint64, "field1");
+  gcc_jit_field *field2 = gcc_jit_context_new_field (ctxt, NULL, double_type, "field2");
+  gcc_jit_field *fields[2] = { field1, field2 };
+  gcc_jit_struct *struct_type = gcc_jit_context_new_struct_type (ctxt, NULL, "testStruct", 2, fields);
+  CHECK_VALUE (gcc_jit_struct_get_field_count(struct_type), 2);
+  CHECK_VALUE (gcc_jit_struct_get_field(struct_type, 0), field1);
+  CHECK_VALUE (gcc_jit_struct_get_field(struct_type, 1), field2);
+  gcc_jit_struct *struct_ty = gcc_jit_type_is_struct(gcc_jit_struct_as_type(struct_type));
+  CHECK_VALUE (struct_ty, struct_type);
+}
+
-- 
2.29.2


^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re: [PATCH] libgccjit: add some reflection functions in the jit C api
  2020-11-03 22:13             ` Antoni Boucher
@ 2021-05-13  8:33               ` Martin Liška
  2021-05-13 21:30               ` David Malcolm
  1 sibling, 0 replies; 35+ messages in thread
From: Martin Liška @ 2021-05-13  8:33 UTC (permalink / raw)
  To: Antoni Boucher, David Malcolm; +Cc: Antoni Boucher via Jit, gcc-patches

@David: PING

On 11/3/20 11:13 PM, Antoni Boucher via Gcc-patches wrote:
> I was missing a check in gcc_jit_struct_get_field, I added it in this new patch.
> 
> On Thu, Oct 15, 2020 at 05:52:33PM -0400, David Malcolm wrote:
>> On Thu, 2020-10-15 at 13:39 -0400, Antoni Boucher wrote:
>>> Thanks. I updated the patch with these changes.
>>
>> Thanks for patch; review below.  Sorry if it seems excessively nitpicky
>> in places.
>>
>>> 2020-09-1  Antoni Boucher  <bouanto@zoho.com>
>>>
>>>     gcc/jit/
>>>             PR target/96889
>>>             * docs/topics/compatibility.rst (LIBGCCJIT_ABI_14): New ABI tag.
>>
>> 15 now.
>>
>>>             * docs/topics/functions.rst: Add documentation for the
>>>             functions gcc_jit_function_get_return_type and
>>>             gcc_jit_function_get_param_count
>>>             * libgccjit.c: New functions:
>>>               * gcc_jit_function_get_return_type;
>>>               * gcc_jit_function_get_param_count;
>>>               * gcc_jit_function_type_get_return_type;
>>>               * gcc_jit_function_type_get_param_count;
>>>               * gcc_jit_function_type_get_param_type;
>>>               * gcc_jit_type_unqualified;
>>>               * gcc_jit_type_is_array;
>>>               * gcc_jit_type_is_bool;
>>>               * gcc_jit_type_is_function_ptr_type;
>>>               * gcc_jit_type_is_int;
>>>               * gcc_jit_type_is_pointer;
>>>               * gcc_jit_type_is_vector;
>>>               * gcc_jit_vector_type_get_element_type;
>>>               * gcc_jit_vector_type_get_num_units;
>>>               * gcc_jit_struct_get_field;
>>>               * gcc_jit_type_is_struct;
>>>               * gcc_jit_struct_get_field_count;
>>
>> This isn't valid ChangeLog format; it will fail the git hooks.
>>
>>>             * libgccjit.h
>>
>> Likewise.
>>
>>>             * jit-recording.h: New functions (is_struct and is_vector)
>>>             * libgccjit.map (LIBGCCJIT_ABI_14): New ABI tag.
>>
>> 15 now.
>>
>>>
>>>     gcc/testsuite/
>>>             PR target/96889
>>>             * jit.dg/all-non-failing-tests.h: Add test-reflection.c.
>>>             * jit.dg/test-reflection.c: New test.
>>
>> [...]
>>
>>
>>> diff --git a/gcc/jit/docs/topics/functions.rst b/gcc/jit/docs/topics/functions.rst
>>> index eb40d64010e..9819c28cda2 100644
>>> --- a/gcc/jit/docs/topics/functions.rst
>>> +++ b/gcc/jit/docs/topics/functions.rst
>>> @@ -171,6 +171,16 @@ Functions
>>>     underlying string, so it is valid to pass in a pointer to an on-stack
>>>     buffer.
>>>
>>> +.. function::  size_t \
>>> +               gcc_jit_function_get_param_count (gcc_jit_function *func)
>>> +
>>> +   Get the number of parameters of the function.
>>> +
>>> +.. function::  gcc_jit_type \*
>>> +               gcc_jit_function_get_return_type (gcc_jit_function *func)
>>> +
>>> +   Get the return type of the function.
>>> +
>>
>> The documentation part of the patch is incomplete: it hasn't been
>> updated to add all the new entrypoints.
>> Also, the return type of gcc_jit_function_get_param_count is
>> inconsistent (size_t above, but ssize_t below).
>>
>>
>>> diff --git a/gcc/jit/jit-recording.h b/gcc/jit/jit-recording.h
>>> index 30e37aff387..525b8bc921d 100644
>>> --- a/gcc/jit/jit-recording.h
>>> +++ b/gcc/jit/jit-recording.h
>>> @@ -538,7 +538,9 @@ public:
>>>    virtual bool is_bool () const = 0;
>>>    virtual type *is_pointer () = 0;
>>>    virtual type *is_array () = 0;
>>> +  virtual struct_ *is_struct () { return NULL; }
>>
>> Can't you use dyn_cast_struct for this?
>> Or is this about looking through decorated_type? e.g. for const and
>> volatile variants?
>>
>> I guess my question is, what is the purpose of gcc_jit_type_is_struct?
>>
>>>    virtual bool is_void () const { return false; }
>>> +  virtual vector_type *is_vector () { return NULL; }
>>
>> Likewise, can't you use dyn_cast_vector_type for this?
>>
>>>    virtual bool has_known_size () const { return true; }
>>>
>>>    bool is_numeric () const
>>> @@ -595,6 +597,8 @@ public:
>>>    bool is_bool () const FINAL OVERRIDE;
>>>    type *is_pointer () FINAL OVERRIDE { return dereference (); }
>>>    type *is_array () FINAL OVERRIDE { return NULL; }
>>> +  vector_type *is_vector () FINAL OVERRIDE { return NULL; }
>>> +  struct_ *is_struct () FINAL OVERRIDE { return NULL; }
>>
>> Likewise, and this is redundant, as it's merely copying the base class
>> implementation.
>>
>>>    bool is_void () const FINAL OVERRIDE { return m_kind == GCC_JIT_TYPE_VOID; }
>>>
>>>  public:
>>> @@ -629,6 +633,8 @@ public:
>>>    bool is_bool () const FINAL OVERRIDE { return false; }
>>>    type *is_pointer () FINAL OVERRIDE { return m_other_type; }
>>>    type *is_array () FINAL OVERRIDE { return NULL; }
>>> +  vector_type *is_vector () FINAL OVERRIDE { return NULL; }
>>> +  struct_ *is_struct () FINAL OVERRIDE { return NULL; }
>>
>> Likewise.
>>
>>
>>> @@ -655,6 +661,7 @@ public:
>>>    bool is_bool () const FINAL OVERRIDE { return m_other_type->is_bool (); }
>>>    type *is_pointer () FINAL OVERRIDE { return m_other_type->is_pointer (); }
>>>    type *is_array () FINAL OVERRIDE { return m_other_type->is_array (); }
>>> +  struct_ *is_struct () FINAL OVERRIDE { return m_other_type->is_struct (); }
>>
>> Aha: with a decorated type you look through the decoration.
>>
>>>  protected:
>>>    type *m_other_type;
>>> @@ -737,6 +744,8 @@ public:
>>>
>>>    void replay_into (replayer *) FINAL OVERRIDE;
>>>
>>> +  vector_type *is_vector () FINAL OVERRIDE { return this; }
>>> +
>>>  private:
>>>    string * make_debug_string () FINAL OVERRIDE;
>>>    void write_reproducer (reproducer &r) FINAL OVERRIDE;
>>> @@ -765,6 +774,8 @@ class array_type : public type
>>>    bool is_bool () const FINAL OVERRIDE { return false; }
>>>    type *is_pointer () FINAL OVERRIDE { return NULL; }
>>>    type *is_array () FINAL OVERRIDE { return m_element_type; }
>>> +  vector_type *is_vector () FINAL OVERRIDE { return NULL; }
>>> +  struct_ *is_struct () FINAL OVERRIDE { return NULL; }
>>
>> Are these redundant?
>>
>>>    int num_elements () { return m_num_elements; }
>>>
>>>    void replay_into (replayer *) FINAL OVERRIDE;
>>> @@ -799,6 +810,8 @@ public:
>>>    bool is_bool () const FINAL OVERRIDE { return false; }
>>>    type *is_pointer () FINAL OVERRIDE { return NULL; }
>>>    type *is_array () FINAL OVERRIDE { return NULL; }
>>> +  vector_type *is_vector () FINAL OVERRIDE { return NULL; }
>>> +  struct_ *is_struct () FINAL OVERRIDE { return NULL; }
>>
>> Likewise.
>>
>>>    void replay_into (replayer *) FINAL OVERRIDE;
>>>
>>> @@ -912,6 +925,7 @@ public:
>>>    bool is_bool () const FINAL OVERRIDE { return false; }
>>>    type *is_pointer () FINAL OVERRIDE { return NULL; }
>>>    type *is_array () FINAL OVERRIDE { return NULL; }
>>> +  vector_type *is_vector () FINAL OVERRIDE { return NULL; }
>>
>> Likewise.
>>
>>>    bool has_known_size () const FINAL OVERRIDE { return m_fields != NULL; }
>>>
>>> @@ -943,6 +957,8 @@ public:
>>>
>>>    const char *access_as_type (reproducer &r) FINAL OVERRIDE;
>>>
>>> +  struct_ *is_struct () FINAL OVERRIDE { return this; }
>>> +
>>>  private:
>>>    string * make_debug_string () FINAL OVERRIDE;
>>>    void write_reproducer (reproducer &r) FINAL OVERRIDE;
>>> diff --git a/gcc/jit/libgccjit.c b/gcc/jit/libgccjit.c
>>> index a00aefc7108..8e6a9e85ff0 100644
>>> --- a/gcc/jit/libgccjit.c
>>> +++ b/gcc/jit/libgccjit.c
>>> @@ -21,6 +21,7 @@ along with GCC; see the file COPYING3.  If not see
>>>  #include "config.h"
>>>  #include "system.h"
>>>  #include "coretypes.h"
>>> +#include "tm.h"
>>
>> Why is this included?  It's not mentioned in the ChangeLog.
>>
>>>  #include "timevar.h"
>>>  #include "typed-splay-tree.h"
>>>  #include "cppbuiltin.h"
>>> @@ -60,6 +61,14 @@ struct gcc_jit_struct : public gcc::jit::recording::struct_
>>>  {
>>>  };
>>>
>>> +struct gcc_jit_function_type : public gcc::jit::recording::function_type
>>> +{
>>> +};
>>> +
>>> +struct gcc_jit_vector_type : public gcc::jit::recording::vector_type
>>> +{
>>> +};
>>> +
>>
>> FWIW these aren't mentioned in the ChangeLog either.
>>
>>>  struct gcc_jit_field : public gcc::jit::recording::field
>>>  {
>>>  };
>>> @@ -510,6 +519,197 @@ gcc_jit_type_get_volatile (gcc_jit_type *type)
>>
>> [...]
>>
>>> +/* Public entrypoint.  See description in libgccjit.h.
>>> +
>>> +   After error-checking, the real work is done by the
>>> +   gcc::jit::recording::function_type::get_param_types method, in
>>> +   jit-recording.c.  */
>>> +
>>> +gcc_jit_type *
>>> +gcc_jit_function_type_get_param_type (gcc_jit_function_type *function_type,
>>> +                int index)
>>> +{
>>> +  RETURN_NULL_IF_FAIL (function_type, NULL, NULL, "NULL struct_type");
>>> +  int num_params = function_type->get_param_types ().length ();
>>> +  gcc::jit::recording::context *ctxt = function_type->m_ctxt;
>>
>> Should check that index >= 0 as well (or make it unsigned).
>>
>> Given that gcc_jit_function_get_param_count returns ssize_t, should
>> that be the type of "index"?
>>
>>> +  RETURN_NULL_IF_FAIL_PRINTF3 (index < num_params,
>>> +                   ctxt, NULL,
>>> +                   "index of %d is too large (%s has %d params)",
>>> +                   index,
>>> +                   function_type->get_debug_string (),
>>> +                   num_params);
>>> +  return (gcc_jit_type *)function_type->get_param_types ()[index];
>>> +}
>>
>> [...]
>>
>>> +extern gcc_jit_field *
>>> +gcc_jit_struct_get_field (gcc_jit_struct *struct_type,
>>> +               int index)
>>> +{
>>> +  RETURN_NULL_IF_FAIL (struct_type, NULL, NULL, "NULL struct type");
>>
>> Similar comments as per gcc_jit_function_type_get_param_type above.
>> Should check here that index is in range (>=0 and < num fields).
>>
>>> +  return (gcc_jit_field *)struct_type->get_fields ()->get_field (index);
>>> +}
>>> +
>>> +/* Public entrypoint.  See description in libgccjit.h.
>>> +
>>> +   After error-checking, this calls the trivial
>>> +   gcc::jit::recording::struct_::get_fields method in
>>> +   jit-recording.h.  */
>>> +
>>> +ssize_t
>>> +gcc_jit_struct_get_field_count (gcc_jit_struct *struct_type)
>>> +{
>>> +  RETURN_VAL_IF_FAIL (struct_type, -1, NULL, NULL, "NULL struct type");
>>> +  return struct_type->get_fields ()->length ();
>>> +}
>>> +
>>
>> [...]
>>
>>> diff --git a/gcc/jit/libgccjit.h b/gcc/jit/libgccjit.h
>>> index 7134841bb07..6056d00a3ea 100644
>>> --- a/gcc/jit/libgccjit.h
>>> +++ b/gcc/jit/libgccjit.h
>>> @@ -96,6 +96,12 @@ typedef struct gcc_jit_field gcc_jit_field;
>>>     the layout for, or an opaque type.  */
>>>  typedef struct gcc_jit_struct gcc_jit_struct;
>>>
>>> +/* A gcc_jit_function_type encapsulates a function type.  */
>>> +typedef struct gcc_jit_function_type gcc_jit_function_type;
>>> +
>>> +/* A gcc_jit_vector_type encapsulates a vector type.  */
>>> +typedef struct gcc_jit_vector_type gcc_jit_vector_type;
>>> +
>>>  /* A gcc_jit_function encapsulates a function: either one that you're
>>>     creating yourself, or a reference to one that you're dynamically
>>>     linking to within the rest of the process.  */
>>> @@ -586,6 +592,61 @@ gcc_jit_type_get_const (gcc_jit_type *type);
>>>  extern gcc_jit_type *
>>>  gcc_jit_type_get_volatile (gcc_jit_type *type);
>>>
>>> +/* Given type "T", return TRUE if the type is an array.  */
>>> +extern gcc_jit_type *
>>> +gcc_jit_type_is_array (gcc_jit_type *type);
>>
>> The comment is unclear; does this actually return the type vs NULL?
>>
>> As noted above, I think we need to think about what happens on
>> qualified types; is stripping them the responsibility of the caller?
>> Should it be?  (I'm thinking "yes", but presumably all this is
>> motivated by your rust hacking).
>>
>> Also, there isn't a type "T" here; the param name is "type", and there
>> isn't a supporting example using "T" as a placeholder.
>> Maybe just lose the 'Given type "T", ' prefix here and below (unless
>> giving a example).
>>
>>> +/* Given type "T", return TRUE if the type is a bool.  */
>>> +extern int
>>> +gcc_jit_type_is_bool (gcc_jit_type *type);
>>
>> I'd prefer "return non-zero" over "return TRUE" (here, and in various
>> places below).
>>
>> Does this check for the "bool" type i.e.:
>>  /* C++'s bool type; also C99's "_Bool" type, aka "bool" if using
>>     stdbool.h.  */
>>  GCC_JIT_TYPE_BOOL,
>> ?
>>
>>> +/* Given type "T", return the function type if it is one.  */
>>
>> ..."or NULL".
>>
>>> +extern gcc_jit_function_type *
>>> +gcc_jit_type_is_function_ptr_type (gcc_jit_type *type);
>>> +
>>> +/* Given a function type, return its return type.  */
>>> +extern gcc_jit_type *
>>> +gcc_jit_function_type_get_return_type (gcc_jit_function_type *function_type);
>>> +
>>> +/* Given a function type, return its number of parameters.  */
>>> +extern ssize_t
>>> +gcc_jit_function_type_get_param_count (gcc_jit_function_type *function_type);
>>> +
>>> +/* Given a function type, return the type of the specified parameter.  */
>>> +extern gcc_jit_type *
>>> +gcc_jit_function_type_get_param_type (gcc_jit_function_type *function_type,
>>> +                int index);
>>> +
>>> +/* Given type "T", return the type pointed by the pointer type
>>> + * or NULL if it's not a pointer.  */
>>> +extern gcc_jit_type *
>>> +gcc_jit_type_is_pointer (gcc_jit_type *type);
>>> +
>>> +/* Given type "T", return TRUE if the type is an int.  */
>>> +extern int
>>> +gcc_jit_type_is_int (gcc_jit_type *type);
>>
>> I'm not sure I understand what this function does, which suggests it's
>> misnamed.  The current name suggests that it checks for the C "int"
>> type, whereas I believe it actually checks for an integral
>> type.  Should it be:
>>
>> extern int
>> gcc_jit_type_is_integral (gcc_jit_type *type);
>>
>> ?
>>
>> What's the output?  Do you merely need nonzero/zero for boolean, or
>> information on the width of the type/signedness, or whatnot?  (perhaps
>> have some out params for extracting width/signedness for when it
>> returns nonzero?)
>>
>> Looking at the testcase, it looks like it currently returns false on
>> the _Bool type.  Is that correct?
>>
>>
>>> +/* Given type "T", return the unqualified type, i.e. for a
>>> + * decorated type, return the type it wraps.  */
>>> +extern gcc_jit_type *
>>> +gcc_jit_type_unqualified (gcc_jit_type *type);
>>
>> "decorated" is a term used inside the implementation, but not in the
>> user-facing docs.
>>
>> How about:
>>
>>  /* Given a type, return the unqualified type, removing "const",
>> "volatile"
>>     and alignment qualifiers.  */
>>
>> or somesuch.
>>
>>> +/* Given type "T", return TRUE if the type is a vector type.  */
>>> +extern gcc_jit_vector_type *
>>> +gcc_jit_type_is_vector (gcc_jit_type *type);
>>
>> As above, this doesn't return TRUE, it's more of a dynamic cast.
>> Likewise about responsibility for qualifiers.
>>
>>> +/* Given type "T", return the struct type or NULL.  */
>>> +extern gcc_jit_struct *
>>> +gcc_jit_type_is_struct (gcc_jit_type *type);
>>
>> Wording could be improved as noted above.
>>
>>> +/* Given a vector type, return the number of units it contains.  */
>>> +extern ssize_t
>>> +gcc_jit_vector_type_get_num_units (gcc_jit_vector_type *vector_type);
>>> +
>>> +/* Given a vector type, return the type of its elements.  */
>>> +extern gcc_jit_type *
>>> +gcc_jit_vector_type_get_element_type (gcc_jit_vector_type *vector_type);
>>> +
>>
>> [...]
>>
>>> @@ -647,6 +708,15 @@ gcc_jit_struct_set_fields (gcc_jit_struct *struct_type,
>>>                 int num_fields,
>>>                 gcc_jit_field **fields);
>>>
>>> +/* Get a field by index.  */
>>> +extern gcc_jit_field *
>>> +gcc_jit_struct_get_field (gcc_jit_struct *struct_type,
>>> +               int index);
>>> +
>>> +/* Get the number of fields.  */
>>> +extern ssize_t
>>> +gcc_jit_struct_get_field_count (gcc_jit_struct *struct_type);
>>
>> Do we need these for unions?  Or skip them for now?
>>
>>> @@ -740,6 +810,14 @@ gcc_jit_function_as_object (gcc_jit_function *func);
>>>  extern gcc_jit_param *
>>>  gcc_jit_function_get_param (gcc_jit_function *func, int index);
>>>
>>> +/* Get the number of params of a function.  */
>>> +extern ssize_t
>>> +gcc_jit_function_get_param_count (gcc_jit_function *func);
>>> +
>>> +/* Get the return type of a function.  */
>>> +extern gcc_jit_type *
>>> +gcc_jit_function_get_return_type (gcc_jit_function *func);
>>
>> Are these redundant if there's a way to ask a gcc_jit_function for its
>> type, and then to use the gcc_jit_function_type_ functions?
>> (I don't mind if they are)
>>
>>> @@ -1518,6 +1596,47 @@ gcc_jit_version_minor (void);
>>>  extern int
>>>  gcc_jit_version_patchlevel (void);
>>>
>>> +#define LIBGCCJIT_HAVE_gcc_jit_function_reflection
>>> +
>>> +/* Reflection functions to get the number of parameters, return type of
>>> +   a function and whether a type is a bool from the C API.
>>> +
>>> +   This API entrypoint was added in LIBGCCJIT_ABI_15; you can test for its
>>> +   presence using
>>> +     #ifdef LIBGCCJIT_HAVE_gcc_jit_function_reflection
>>> +*/
>>
>> This has become a big mixture of things beyond just function
>> reflection, so I think I'd prefer it if each entrypoint "funcname" had
>> its own "LIBGCCJIT_HAVE_funcname" define.  Or just "REFLECTION" rather
>> than "function_reflection", that's probably simpler.
>> Note that the existing "HAVE_foo" defines are lowercase "foo" when it's
>> an actual entrypoint named "foo", and are uppercase otherwise e.g.
>> LIBGCCJIT_HAVE_SWITCH_STATEMENTS and LIBGCCJIT_HAVE_TIMING_API.
>>
>>> +extern gcc_jit_type *
>>> +gcc_jit_function_get_return_type (gcc_jit_function *func);
>>> +extern ssize_t
>>> +gcc_jit_function_get_param_count (gcc_jit_function *func);
>>> +extern gcc_jit_type *
>>> +gcc_jit_type_is_array (gcc_jit_type *type);
>>> +extern int
>>> +gcc_jit_type_is_bool (gcc_jit_type *type);
>>> +extern gcc_jit_function_type *
>>> +gcc_jit_type_is_function_ptr_type (gcc_jit_type *type);
>>> +extern gcc_jit_type *
>>> +gcc_jit_function_type_get_return_type (gcc_jit_function_type *function_type);
>>> +extern ssize_t
>>> +gcc_jit_function_type_get_param_count (gcc_jit_function_type *function_type);
>>> +extern gcc_jit_type *
>>> +gcc_jit_function_type_get_param_type (gcc_jit_function_type *function_type,
>>> +                int index);
>>> +extern int
>>> +gcc_jit_type_is_int (gcc_jit_type *type);
>>> +extern gcc_jit_type *
>>> +gcc_jit_type_is_pointer (gcc_jit_type *type);
>>> +extern gcc_jit_vector_type *
>>> +gcc_jit_type_is_vector (gcc_jit_type *type);
>>> +extern gcc_jit_struct *
>>> +gcc_jit_type_is_struct (gcc_jit_type *type);
>>> +extern ssize_t
>>> +gcc_jit_vector_type_get_num_units (gcc_jit_vector_type *vector_type);
>>> +extern gcc_jit_type *
>>> +gcc_jit_vector_type_get_element_type (gcc_jit_vector_type *vector_type);
>>> +extern gcc_jit_type *
>>> +gcc_jit_type_unqualified (gcc_jit_type *type);
>>
>> Is this part of the patch a duplicate copy of the various things added
>> above?  Perhaps copy-and-paste error, or am I misreading this?
>>
>> [...]
>>
>> Hope this is constructive
>> Dave
>>


^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re: [PATCH] libgccjit: add some reflection functions in the jit C api
  2020-11-03 22:13             ` Antoni Boucher
  2021-05-13  8:33               ` Martin Liška
@ 2021-05-13 21:30               ` David Malcolm
  2021-05-14  2:11                 ` Antoni Boucher
  2021-05-26  0:19                 ` Antoni Boucher
  1 sibling, 2 replies; 35+ messages in thread
From: David Malcolm @ 2021-05-13 21:30 UTC (permalink / raw)
  To: Antoni Boucher; +Cc: Andrea Corallo, Antoni Boucher via Jit, gcc-patches

On Tue, 2020-11-03 at 17:13 -0500, Antoni Boucher wrote:
> I was missing a check in gcc_jit_struct_get_field, I added it in this
> new patch.
> 

Sorry about the long delay in reviewing this patch.

The main high-level points are:
- currently the get_*_count functions return "ssize_t" - why?  Only
unsigned values are meaningful; shouldn't they return "size_t" instead?

- the various "lookup by index" functions take "int" i.e. signed, but
only >= 0 is meaningful.  I think it makes sense to make them take
size_t instead.

Sorry if we covered that before in the review, it's been a while.

Various nitpicks inline below...

[...snip...]
 
> diff --git a/gcc/jit/docs/topics/compatibility.rst b/gcc/jit/docs/topics/compatibility.rst
> index 6bfa101ed71..236e5c72d81 100644
> --- a/gcc/jit/docs/topics/compatibility.rst
> +++ b/gcc/jit/docs/topics/compatibility.rst
> @@ -226,3 +226,44 @@ entrypoints:
>  --------------------
>  ``LIBGCCJIT_ABI_14`` covers the addition of
>  :func:`gcc_jit_global_set_initializer`
> +
> +.. _LIBGCCJIT_ABI_15:
> +
> +``LIBGCCJIT_ABI_15``
> +--------------------
> +``LIBGCCJIT_ABI_15`` covers the addition of reflection functions via API
> +entrypoints:

This needs updating, as I used LIBGCCJIT_ABI_15 for inline asm.

[...snip...]

> diff --git a/gcc/jit/docs/topics/functions.rst b/gcc/jit/docs/topics/functions.rst
> index eb40d64010e..aa6de87282d 100644
> --- a/gcc/jit/docs/topics/functions.rst
> +++ b/gcc/jit/docs/topics/functions.rst
> @@ -171,6 +171,16 @@ Functions
>     underlying string, so it is valid to pass in a pointer to an on-stack
>     buffer.
>  
> +.. function::  ssize_t \
> +               gcc_jit_function_get_param_count (gcc_jit_function *func)
> +
> +   Get the number of parameters of the function.
> +
> +.. function::  gcc_jit_type \*
> +               gcc_jit_function_get_return_type (gcc_jit_function *func)
> +
> +   Get the return type of the function.

As noted before, this doesn't yet document all the new entrypoints; I
think you wanted to hold off until all the details were thrashed out,
but hopefully we're close.

The documentation for an entrypoint should specify which ABI it was
added in.

[...snip...]

> +/* Public entrypoint.  See description in libgccjit.h.
> +
> +   After error-checking, the real work is done by the
> +   gcc::jit::recording::type::is_struct method, in
> +   jit-recording.c.  */
> +
> +gcc_jit_struct *
> +gcc_jit_type_is_struct (gcc_jit_type *type)
> +{
> +  RETURN_NULL_IF_FAIL (type, NULL, NULL, "NULL type");
> +  gcc::jit::recording::struct_ *struct_type = type->is_struct ();
> +  return (gcc_jit_struct *)struct_type;
> +}
> +
> +/* Public entrypoint.  See description in libgccjit.h.
> +
> +   After error-checking, the real work is done by the
> +   gcc::jit::recording::vector_type::get_num_units method, in
> +   jit-recording.c.  */
> +
> +ssize_t
> +gcc_jit_vector_type_get_num_units (gcc_jit_vector_type *vector_type)
> +{
> +  RETURN_VAL_IF_FAIL (vector_type, -1, NULL, NULL, "NULL vector_type");
> +  return vector_type->get_num_units ();
> +}
> +
> +/* Public entrypoint.  See description in libgccjit.h.
> +
> +   After error-checking, the real work is done by the
> +   gcc::jit::recording::vector_type::get_element_type method, in
> +   jit-recording.c.  */
> +
> +gcc_jit_type *
> +gcc_jit_vector_type_get_element_type (gcc_jit_vector_type *vector_type)
> +{
> +  RETURN_NULL_IF_FAIL (vector_type, NULL, NULL, "NULL vector_type");
> +  return (gcc_jit_type *)vector_type->get_element_type ();
> +}
> +
> +/* Public entrypoint.  See description in libgccjit.h.
> +
> +   After error-checking, the real work is done by the
> +   gcc::jit::recording::type::unqualified method, in
> +   jit-recording.c.  */
> +
> +gcc_jit_type *
> +gcc_jit_type_unqualified (gcc_jit_type *type)
> +{
> +  RETURN_NULL_IF_FAIL (type, NULL, NULL, "NULL type");
> +
> +  return (gcc_jit_type *)type->unqualified ();
> +}
> +
> +/* Public entrypoint.  See description in libgccjit.h.
> +
> +   After error-checking, the real work is done by the
> +   gcc::jit::recording::type::dyn_cast_function_type method, in
> +   jit-recording.c.  */
> +
> +gcc_jit_function_type *
> +gcc_jit_type_is_function_ptr_type (gcc_jit_type *type)
> +{
> +  RETURN_NULL_IF_FAIL (type, NULL, NULL, "NULL type");
> +  gcc::jit::recording::type *func_ptr_type = type->dereference ();
> +  RETURN_NULL_IF_FAIL (func_ptr_type, NULL, NULL, "NULL type");
> +  gcc::jit::recording::function_type *func_type =
> +    func_ptr_type->dyn_cast_function_type ();
> +  RETURN_NULL_IF_FAIL (func_type, NULL, NULL, "NULL type");

I notice that the other new "*_is_*" functions don't fail if the
dyncast returns NULL, whereas this one does.

RETURN_NULL_IF_FAIL calls jit_error; do we really want that?  It seems
more consistent to have it return NULL without an error for the case
where "type" isn't a function ptr type.

> +
> +  return (gcc_jit_function_type *)func_type;
> +}
> +
> +/* Public entrypoint.  See description in libgccjit.h.
> +
> +   After error-checking, the real work is done by the
> +   gcc::jit::recording::function_type::get_return_type method, in
> +   jit-recording.c.  */
> +
> +gcc_jit_type *
> +gcc_jit_function_type_get_return_type (gcc_jit_function_type *function_type)
> +{
> +  RETURN_NULL_IF_FAIL (function_type, NULL, NULL, "NULL struct_type");

Wrong error message; should be "NULL function_type".


> +  return (gcc_jit_type *)function_type->get_return_type ();
> +}
> +
> +/* Public entrypoint.  See description in libgccjit.h.
> +
> +   After error-checking, the real work is done by the
> +   gcc::jit::recording::function_type::get_param_types method, in
> +   jit-recording.c.  */
> +
> +ssize_t
> +gcc_jit_function_type_get_param_count (gcc_jit_function_type *function_type)
> +{
> +  RETURN_VAL_IF_FAIL (function_type, -1, NULL, NULL, "NULL struct_type");

Wrong error message; should be "NULL function_type".

> +  return function_type->get_param_types ().length ();
> +}
> +
> +/* Public entrypoint.  See description in libgccjit.h.
> +
> +   After error-checking, the real work is done by the
> +   gcc::jit::recording::function_type::get_param_types method, in
> +   jit-recording.c.  */
> +
> +gcc_jit_type *
> +gcc_jit_function_type_get_param_type (gcc_jit_function_type *function_type,
> +				int index)
> +{
> +  RETURN_NULL_IF_FAIL (function_type, NULL, NULL, "NULL struct_type");

Wrong error message; should be "NULL function_type".


> +  int num_params = function_type->get_param_types ().length ();
> +  gcc::jit::recording::context *ctxt = function_type->m_ctxt;

"index" should either be unsigned, or we need to check here for >= 0.

> +  RETURN_NULL_IF_FAIL_PRINTF3 (index < num_params,
> +			       ctxt, NULL,
> +			       "index of %d is too large (%s has %d params)",
> +			       index,
> +			       function_type->get_debug_string (),
> +			       num_params);
> +  return (gcc_jit_type *)function_type->get_param_types ()[index];
> +}
> +
>  /* Public entrypoint.  See description in libgccjit.h.
>  
>     After error-checking, the real work is done by the
> @@ -731,6 +930,36 @@ gcc_jit_struct_set_fields (gcc_jit_struct *struct_type,
>  			   (gcc::jit::recording::field **)fields);
>  }
>  
> +
> +/* Public entrypoint.  See description in libgccjit.h.
> +
> +   After error-checking, the real work is done by the
> +   gcc::jit::recording::fields::get_field method in
> +   jit-recording.c.  */
> +extern gcc_jit_field *
> +gcc_jit_struct_get_field (gcc_jit_struct *struct_type,
> +			   int index)
> +{
> +  RETURN_NULL_IF_FAIL (struct_type, NULL, NULL, "NULL struct type");
> +  RETURN_NULL_IF_FAIL (struct_type->get_fields (), NULL, NULL, "NULL struct fields");

"index" should either be unsigned, or we need to check here for >= 0.

> +  RETURN_NULL_IF_FAIL (index < struct_type->get_fields ()->length (), NULL,
> +				NULL, "NULL struct type");
> +  return (gcc_jit_field *)struct_type->get_fields ()->get_field (index);
> +}

[...snip...]

> diff --git a/gcc/jit/libgccjit.h b/gcc/jit/libgccjit.h
> index 7134841bb07..db4ccffb41c 100644
> --- a/gcc/jit/libgccjit.h
> +++ b/gcc/jit/libgccjit.h
> @@ -96,6 +96,12 @@ typedef struct gcc_jit_field gcc_jit_field;
>     the layout for, or an opaque type.  */
>  typedef struct gcc_jit_struct gcc_jit_struct;
>  
> +/* A gcc_jit_function_type encapsulates a function type.  */
> +typedef struct gcc_jit_function_type gcc_jit_function_type;
> +
> +/* A gcc_jit_vector_type encapsulates a vector type.  */
> +typedef struct gcc_jit_vector_type gcc_jit_vector_type;
> +

Please add these to the ASCII art inheritance diagram immediately
above:
  typedef struct gcc_jit_object gcc_jit_object;

[...snip...]

>  /* Unions work similarly to structs.  */
>  extern gcc_jit_type *
>  gcc_jit_context_new_union_type (gcc_jit_context *ctxt,
> @@ -1518,6 +1533,78 @@ gcc_jit_version_minor (void);
>  extern int
>  gcc_jit_version_patchlevel (void);
>  
> +#define LIBGCCJIT_HAVE_REFLECTION
> +
> +/* Reflection functions to get the number of parameters, return type of
> +   a function and whether a type is a bool from the C API.
> +
> +   This API entrypoint was added in LIBGCCJIT_ABI_15; you can test for its
> +   presence using
> +     #ifdef LIBGCCJIT_HAVE_REFLECTION
> +*/
> +/* Get the return type of a function.  */
> +extern gcc_jit_type *
> +gcc_jit_function_get_return_type (gcc_jit_function *func);
> +
> +/* Get the number of params of a function.  */
> +extern ssize_t
> +gcc_jit_function_get_param_count (gcc_jit_function *func);

You're using ssize_t here, why?  Wouldn't size_t be better?
The count can't be negative.

Should we use size_t for indexes, rather than "int"?

(this happens in various places e.g.
gcc_jit_function_type_get_param_count and
gcc_jit_vector_type_get_num_units)

[...snip...]

> diff --git a/gcc/jit/libgccjit.map b/gcc/jit/libgccjit.map
> index a6e67e781a4..720b6ca286f 100644
> --- a/gcc/jit/libgccjit.map
> +++ b/gcc/jit/libgccjit.map
> @@ -192,3 +192,24 @@ LIBGCCJIT_ABI_14 {
>    global:
>      gcc_jit_global_set_initializer;
>  } LIBGCCJIT_ABI_13;
> +
> +LIBGCCJIT_ABI_15 {
> +  global:
> +    gcc_jit_function_get_return_type;
> +    gcc_jit_function_get_param_count;
> +    gcc_jit_function_type_get_return_type;
> +    gcc_jit_function_type_get_param_count;
> +    gcc_jit_function_type_get_param_type;
> +    gcc_jit_type_unqualified;
> +    gcc_jit_type_is_array;
> +    gcc_jit_type_is_bool;
> +    gcc_jit_type_is_function_ptr_type;
> +    gcc_jit_type_is_integral;
> +    gcc_jit_type_is_pointer;
> +    gcc_jit_type_is_vector;
> +    gcc_jit_vector_type_get_element_type;
> +    gcc_jit_vector_type_get_num_units;
> +    gcc_jit_struct_get_field;
> +    gcc_jit_type_is_struct;
> +    gcc_jit_struct_get_field_count;
> +} LIBGCCJIT_ABI_14;

As noted above, this will need to be LIBGCCJIT_ABI_16 as I used
LIBGCCJIT_ABI_15 for inline asm.

[...snip...]

> diff --git a/gcc/testsuite/jit.dg/test-reflection.c b/gcc/testsuite/jit.dg/test-reflection.c
> new file mode 100644
> index 00000000000..b3cf2942f3a
> --- /dev/null
> +++ b/gcc/testsuite/jit.dg/test-reflection.c
> @@ -0,0 +1,89 @@
> +#include <stdlib.h>
> +#include <stdio.h>
> +
> +#include "libgccjit.h"
> +
> +#include "harness.h"
> +
> +void
> +create_code (gcc_jit_context *ctxt, void *user_data)
> +{
> +  /* Do nothing.  */
> +}
> +
> +void
> +verify_code (gcc_jit_context *ctxt, gcc_jit_result *result)
> +{
> +  /* Get the built-in functions.  */
> +  gcc_jit_function *builtin_sin =
> +    gcc_jit_context_get_builtin_function (ctxt, "sin");
> +
> +  CHECK_VALUE (gcc_jit_function_get_param_count(builtin_sin), 1);
> +
> +  gcc_jit_type *double_type =
> +    gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_DOUBLE);
> +  CHECK_VALUE (gcc_jit_function_get_return_type(builtin_sin), double_type);
> +  CHECK (!gcc_jit_type_is_integral(double_type));
> +
> +  gcc_jit_type *bool_type =
> +    gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_BOOL);
> +  CHECK (gcc_jit_type_is_bool(bool_type));
> +  CHECK (!gcc_jit_type_is_integral(bool_type));
> +
> +  gcc_jit_type *aligned_bool_type =
> +    gcc_jit_type_get_aligned(gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_BOOL), 8);
> +  CHECK (gcc_jit_type_is_bool(aligned_bool_type));
> +  CHECK (bool_type != aligned_bool_type);
> +  CHECK_VALUE (gcc_jit_type_unqualified(aligned_bool_type), bool_type);
> +
> +  CHECK_VALUE (gcc_jit_type_unqualified(gcc_jit_type_get_const(bool_type)), bool_type);
> +  CHECK_VALUE (gcc_jit_type_unqualified(gcc_jit_type_get_volatile(bool_type)), bool_type);
> +
> +  gcc_jit_type *int64 =
> +    gcc_jit_context_get_int_type(ctxt, 8, 1);
> +  CHECK (gcc_jit_type_is_integral(int64));
> +  gcc_jit_type *uint64 =
> +    gcc_jit_context_get_int_type(ctxt, 8, 0);
> +  CHECK (gcc_jit_type_is_integral(uint64));
> +  gcc_jit_type *int8 =
> +    gcc_jit_context_get_int_type(ctxt, 1, 1);
> +  CHECK (gcc_jit_type_is_integral(int8));
> +  gcc_jit_type *uint8 =
> +    gcc_jit_context_get_int_type(ctxt, 1, 0);
> +  CHECK (gcc_jit_type_is_integral(uint8));
> +
> +  CHECK (!gcc_jit_type_is_vector(double_type));
> +  gcc_jit_type *vec_type = gcc_jit_type_get_vector (double_type, 4);
> +  gcc_jit_vector_type *vector_type = gcc_jit_type_is_vector(vec_type);
> +  CHECK (vector_type);
> +  CHECK (vec_type != double_type);
> +  CHECK_VALUE (gcc_jit_vector_type_get_element_type(vector_type), double_type);
> +  CHECK_VALUE (gcc_jit_vector_type_get_num_units(vector_type), 4);
> +
> +  CHECK (!gcc_jit_type_is_pointer(double_type));
> +  CHECK_VALUE (gcc_jit_type_is_pointer(gcc_jit_type_get_pointer(double_type)), double_type);
> +
> +  gcc_jit_type* params[2] = {int8, uint64};
> +  gcc_jit_type *function_ptr_type = gcc_jit_context_new_function_ptr_type(ctxt, NULL, int64, 2, params, 0);
> +  gcc_jit_function_type *function_type = gcc_jit_type_is_function_ptr_type (function_ptr_type);
> +  CHECK (function_type);
> +  int param_count = gcc_jit_function_type_get_param_count(function_type);
> +  CHECK_VALUE (param_count, 2);
> +  gcc_jit_type *return_type = gcc_jit_function_type_get_return_type(function_type);
> +  CHECK_VALUE (return_type, int64);
> +  gcc_jit_type *param1 = gcc_jit_function_type_get_param_type(function_type, 0);
> +  CHECK_VALUE (param1, int8);
> +  gcc_jit_type *param2 = gcc_jit_function_type_get_param_type(function_type, 1);
> +  CHECK_VALUE (param2, uint64);
> +
> +  gcc_jit_field *field1 = gcc_jit_context_new_field (ctxt, NULL, uint64, "field1");
> +  gcc_jit_field *field2 = gcc_jit_context_new_field (ctxt, NULL, double_type, "field2");
> +  gcc_jit_field *fields[2] = { field1, field2 };
> +  gcc_jit_struct *struct_type = gcc_jit_context_new_struct_type (ctxt, NULL, "testStruct", 2, fields);
> +  CHECK_VALUE (gcc_jit_struct_get_field_count(struct_type), 2);
> +  CHECK_VALUE (gcc_jit_struct_get_field(struct_type, 0), field1);
> +  CHECK_VALUE (gcc_jit_struct_get_field(struct_type, 1), field2);
> +  gcc_jit_struct *struct_ty = gcc_jit_type_is_struct(gcc_jit_struct_as_type(struct_type));
> +  CHECK_VALUE (struct_ty, struct_type);


I think this is missing test coverage for the various gcc_jit_type_is_*
entrypoints gracefully returning NULL when the type passed to them is
wrong (e.g. a non-struct type passed to gcc_jit_type_is_struct, etc)

Hope this is constructive; sorry again about the delay in reviewing it.
Dave



^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re: [PATCH] libgccjit: add some reflection functions in the jit C api
  2021-05-13 21:30               ` David Malcolm
@ 2021-05-14  2:11                 ` Antoni Boucher
  2021-05-26  0:19                 ` Antoni Boucher
  1 sibling, 0 replies; 35+ messages in thread
From: Antoni Boucher @ 2021-05-14  2:11 UTC (permalink / raw)
  To: David Malcolm; +Cc: Andrea Corallo, Antoni Boucher via Jit, gcc-patches

[-- Attachment #1: Type: text/plain, Size: 18494 bytes --]

Thanks for your reviews.

I attached the new patch to this email.

See answers below:

Le jeudi 13 mai 2021 à 17:30 -0400, David Malcolm a écrit :
> On Tue, 2020-11-03 at 17:13 -0500, Antoni Boucher wrote:
> > I was missing a check in gcc_jit_struct_get_field, I added it in
> > this
> > new patch.
> > 
> 
> Sorry about the long delay in reviewing this patch.
> 
> The main high-level points are:
> - currently the get_*_count functions return "ssize_t" - why?  Only
> unsigned values are meaningful; shouldn't they return "size_t"
> instead?

For those, I had this question in a previous email:

That seemed off to return NULL for the functions returning a 
size_t to indicate an error. So I changed it to return -1 (and return
type to ssize_t). Is that the proper way to indicate an error?

Once I know the answer for this error handling question, I'll fix the
types.

> - the various "lookup by index" functions take "int" i.e. signed, but
> only >= 0 is meaningful.  I think it makes sense to make them take
> size_t instead.

That's fixed in the new patch.

> Sorry if we covered that before in the review, it's been a while.
> 
> Various nitpicks inline below...
> 
> [...snip...]
>  
> > diff --git a/gcc/jit/docs/topics/compatibility.rst
> > b/gcc/jit/docs/topics/compatibility.rst
> > index 6bfa101ed71..236e5c72d81 100644
> > --- a/gcc/jit/docs/topics/compatibility.rst
> > +++ b/gcc/jit/docs/topics/compatibility.rst
> > @@ -226,3 +226,44 @@ entrypoints:
> >  --------------------
> >  ``LIBGCCJIT_ABI_14`` covers the addition of
> >  :func:`gcc_jit_global_set_initializer`
> > +
> > +.. _LIBGCCJIT_ABI_15:
> > +
> > +``LIBGCCJIT_ABI_15``
> > +--------------------
> > +``LIBGCCJIT_ABI_15`` covers the addition of reflection functions via
> > API
> > +entrypoints:
> 
> This needs updating, as I used LIBGCCJIT_ABI_15 for inline asm.

This was updated for the new patch.

> [...snip...]
> 
> > diff --git a/gcc/jit/docs/topics/functions.rst
> > b/gcc/jit/docs/topics/functions.rst
> > index eb40d64010e..aa6de87282d 100644
> > --- a/gcc/jit/docs/topics/functions.rst
> > +++ b/gcc/jit/docs/topics/functions.rst
> > @@ -171,6 +171,16 @@ Functions
> >     underlying string, so it is valid to pass in a pointer to an on-
> > stack
> >     buffer.
> >  
> > +.. function::  ssize_t \
> > +               gcc_jit_function_get_param_count (gcc_jit_function
> > *func)
> > +
> > +   Get the number of parameters of the function.
> > +
> > +.. function::  gcc_jit_type \*
> > +               gcc_jit_function_get_return_type (gcc_jit_function
> > *func)
> > +
> > +   Get the return type of the function.
> 
> As noted before, this doesn't yet document all the new entrypoints; I
> think you wanted to hold off until all the details were thrashed out,
> but hopefully we're close.
> 
> The documentation for an entrypoint should specify which ABI it was
> added in.

The documentation was added in the new patch.

> [...snip...]
> 
> > +/* Public entrypoint.  See description in libgccjit.h.
> > +
> > +   After error-checking, the real work is done by the
> > +   gcc::jit::recording::type::is_struct method, in
> > +   jit-recording.c.  */
> > +
> > +gcc_jit_struct *
> > +gcc_jit_type_is_struct (gcc_jit_type *type)
> > +{
> > +  RETURN_NULL_IF_FAIL (type, NULL, NULL, "NULL type");
> > +  gcc::jit::recording::struct_ *struct_type = type->is_struct ();
> > +  return (gcc_jit_struct *)struct_type;
> > +}
> > +
> > +/* Public entrypoint.  See description in libgccjit.h.
> > +
> > +   After error-checking, the real work is done by the
> > +   gcc::jit::recording::vector_type::get_num_units method, in
> > +   jit-recording.c.  */
> > +
> > +ssize_t
> > +gcc_jit_vector_type_get_num_units (gcc_jit_vector_type
> > *vector_type)
> > +{
> > +  RETURN_VAL_IF_FAIL (vector_type, -1, NULL, NULL, "NULL
> > vector_type");
> > +  return vector_type->get_num_units ();
> > +}
> > +
> > +/* Public entrypoint.  See description in libgccjit.h.
> > +
> > +   After error-checking, the real work is done by the
> > +   gcc::jit::recording::vector_type::get_element_type method, in
> > +   jit-recording.c.  */
> > +
> > +gcc_jit_type *
> > +gcc_jit_vector_type_get_element_type (gcc_jit_vector_type
> > *vector_type)
> > +{
> > +  RETURN_NULL_IF_FAIL (vector_type, NULL, NULL, "NULL
> > vector_type");
> > +  return (gcc_jit_type *)vector_type->get_element_type ();
> > +}
> > +
> > +/* Public entrypoint.  See description in libgccjit.h.
> > +
> > +   After error-checking, the real work is done by the
> > +   gcc::jit::recording::type::unqualified method, in
> > +   jit-recording.c.  */
> > +
> > +gcc_jit_type *
> > +gcc_jit_type_unqualified (gcc_jit_type *type)
> > +{
> > +  RETURN_NULL_IF_FAIL (type, NULL, NULL, "NULL type");
> > +
> > +  return (gcc_jit_type *)type->unqualified ();
> > +}
> > +
> > +/* Public entrypoint.  See description in libgccjit.h.
> > +
> > +   After error-checking, the real work is done by the
> > +   gcc::jit::recording::type::dyn_cast_function_type method, in
> > +   jit-recording.c.  */
> > +
> > +gcc_jit_function_type *
> > +gcc_jit_type_is_function_ptr_type (gcc_jit_type *type)
> > +{
> > +  RETURN_NULL_IF_FAIL (type, NULL, NULL, "NULL type");
> > +  gcc::jit::recording::type *func_ptr_type = type->dereference ();
> > +  RETURN_NULL_IF_FAIL (func_ptr_type, NULL, NULL, "NULL type");
> > +  gcc::jit::recording::function_type *func_type =
> > +    func_ptr_type->dyn_cast_function_type ();
> > +  RETURN_NULL_IF_FAIL (func_type, NULL, NULL, "NULL type");
> 
> I notice that the other new "*_is_*" functions don't fail if the
> dyncast returns NULL, whereas this one does.
>
> RETURN_NULL_IF_FAIL calls jit_error; do we really want that?  It
> seems
> more consistent to have it return NULL without an error for the case
> where "type" isn't a function ptr type.

This is fixed in the patch.

> 
> > +
> > +  return (gcc_jit_function_type *)func_type;
> > +}
> > +
> > +/* Public entrypoint.  See description in libgccjit.h.
> > +
> > +   After error-checking, the real work is done by the
> > +   gcc::jit::recording::function_type::get_return_type method, in
> > +   jit-recording.c.  */
> > +
> > +gcc_jit_type *
> > +gcc_jit_function_type_get_return_type (gcc_jit_function_type
> > *function_type)
> > +{
> > +  RETURN_NULL_IF_FAIL (function_type, NULL, NULL, "NULL
> > struct_type");
> 
> Wrong error message; should be "NULL function_type".

Fixed in the patch.

> 
> 
> > +  return (gcc_jit_type *)function_type->get_return_type ();
> > +}
> > +
> > +/* Public entrypoint.  See description in libgccjit.h.
> > +
> > +   After error-checking, the real work is done by the
> > +   gcc::jit::recording::function_type::get_param_types method, in
> > +   jit-recording.c.  */
> > +
> > +ssize_t
> > +gcc_jit_function_type_get_param_count (gcc_jit_function_type
> > *function_type)
> > +{
> > +  RETURN_VAL_IF_FAIL (function_type, -1, NULL, NULL, "NULL
> > struct_type");
> 
> Wrong error message; should be "NULL function_type".
Fixed in the patch
> 
> > +  return function_type->get_param_types ().length ();
> > +}
> > +
> > +/* Public entrypoint.  See description in libgccjit.h.
> > +
> > +   After error-checking, the real work is done by the
> > +   gcc::jit::recording::function_type::get_param_types method, in
> > +   jit-recording.c.  */
> > +
> > +gcc_jit_type *
> > +gcc_jit_function_type_get_param_type (gcc_jit_function_type
> > *function_type,
> > +                               int index)
> > +{
> > +  RETURN_NULL_IF_FAIL (function_type, NULL, NULL, "NULL
> > struct_type");
> 
> Wrong error message; should be "NULL function_type".
Fixed in the patch.
> 
> 
> > +  int num_params = function_type->get_param_types ().length ();
> > +  gcc::jit::recording::context *ctxt = function_type->m_ctxt;
> 
> "index" should either be unsigned, or we need to check here for >= 0.
> 
> > +  RETURN_NULL_IF_FAIL_PRINTF3 (index < num_params,
> > +                              ctxt, NULL,
> > +                              "index of %d is too large (%s has %d
> > params)",
> > +                              index,
> > +                              function_type->get_debug_string (),
> > +                              num_params);
> > +  return (gcc_jit_type *)function_type->get_param_types ()[index];
> > +}
> > +
> >  /* Public entrypoint.  See description in libgccjit.h.
> >  
> >     After error-checking, the real work is done by the
> > @@ -731,6 +930,36 @@ gcc_jit_struct_set_fields (gcc_jit_struct
> > *struct_type,
> >                            (gcc::jit::recording::field **)fields);
> >  }
> >  
> > +
> > +/* Public entrypoint.  See description in libgccjit.h.
> > +
> > +   After error-checking, the real work is done by the
> > +   gcc::jit::recording::fields::get_field method in
> > +   jit-recording.c.  */
> > +extern gcc_jit_field *
> > +gcc_jit_struct_get_field (gcc_jit_struct *struct_type,
> > +                          int index)
> > +{
> > +  RETURN_NULL_IF_FAIL (struct_type, NULL, NULL, "NULL struct
> > type");
> > +  RETURN_NULL_IF_FAIL (struct_type->get_fields (), NULL, NULL,
> > "NULL struct fields");
> 
> "index" should either be unsigned, or we need to check here for >= 0.
Fixed in the patch.
> 
> > +  RETURN_NULL_IF_FAIL (index < struct_type->get_fields ()->length
> > (), NULL,
> > +                               NULL, "NULL struct type");
> > +  return (gcc_jit_field *)struct_type->get_fields ()->get_field
> > (index);
> > +}
> 
> [...snip...]
> 
> > diff --git a/gcc/jit/libgccjit.h b/gcc/jit/libgccjit.h
> > index 7134841bb07..db4ccffb41c 100644
> > --- a/gcc/jit/libgccjit.h
> > +++ b/gcc/jit/libgccjit.h
> > @@ -96,6 +96,12 @@ typedef struct gcc_jit_field gcc_jit_field;
> >     the layout for, or an opaque type.  */
> >  typedef struct gcc_jit_struct gcc_jit_struct;
> >  
> > +/* A gcc_jit_function_type encapsulates a function type.  */
> > +typedef struct gcc_jit_function_type gcc_jit_function_type;
> > +
> > +/* A gcc_jit_vector_type encapsulates a vector type.  */
> > +typedef struct gcc_jit_vector_type gcc_jit_vector_type;
> > +
> 
> Please add these to the ASCII art inheritance diagram immediately
> above:
>   typedef struct gcc_jit_object gcc_jit_object;
Done.
> 
> [...snip...]
> 
> >  /* Unions work similarly to structs.  */
> >  extern gcc_jit_type *
> >  gcc_jit_context_new_union_type (gcc_jit_context *ctxt,
> > @@ -1518,6 +1533,78 @@ gcc_jit_version_minor (void);
> >  extern int
> >  gcc_jit_version_patchlevel (void);
> >  
> > +#define LIBGCCJIT_HAVE_REFLECTION
> > +
> > +/* Reflection functions to get the number of parameters, return
> > type of
> > +   a function and whether a type is a bool from the C API.
> > +
> > +   This API entrypoint was added in LIBGCCJIT_ABI_15; you can test
> > for its
> > +   presence using
> > +     #ifdef LIBGCCJIT_HAVE_REFLECTION
> > +*/
> > +/* Get the return type of a function.  */
> > +extern gcc_jit_type *
> > +gcc_jit_function_get_return_type (gcc_jit_function *func);
> > +
> > +/* Get the number of params of a function.  */
> > +extern ssize_t
> > +gcc_jit_function_get_param_count (gcc_jit_function *func);
> 
> You're using ssize_t here, why?  Wouldn't size_t be better?
> The count can't be negative.
As explained aboved, it is to indicate an error.
> 
> Should we use size_t for indexes, rather than "int"?
> 
> (this happens in various places e.g.
> gcc_jit_function_type_get_param_count and
> gcc_jit_vector_type_get_num_units)
> 
> [...snip...]
> 
> > diff --git a/gcc/jit/libgccjit.map b/gcc/jit/libgccjit.map
> > index a6e67e781a4..720b6ca286f 100644
> > --- a/gcc/jit/libgccjit.map
> > +++ b/gcc/jit/libgccjit.map
> > @@ -192,3 +192,24 @@ LIBGCCJIT_ABI_14 {
> >    global:
> >      gcc_jit_global_set_initializer;
> >  } LIBGCCJIT_ABI_13;
> > +
> > +LIBGCCJIT_ABI_15 {
> > +  global:
> > +    gcc_jit_function_get_return_type;
> > +    gcc_jit_function_get_param_count;
> > +    gcc_jit_function_type_get_return_type;
> > +    gcc_jit_function_type_get_param_count;
> > +    gcc_jit_function_type_get_param_type;
> > +    gcc_jit_type_unqualified;
> > +    gcc_jit_type_is_array;
> > +    gcc_jit_type_is_bool;
> > +    gcc_jit_type_is_function_ptr_type;
> > +    gcc_jit_type_is_integral;
> > +    gcc_jit_type_is_pointer;
> > +    gcc_jit_type_is_vector;
> > +    gcc_jit_vector_type_get_element_type;
> > +    gcc_jit_vector_type_get_num_units;
> > +    gcc_jit_struct_get_field;
> > +    gcc_jit_type_is_struct;
> > +    gcc_jit_struct_get_field_count;
> > +} LIBGCCJIT_ABI_14;
> 
> As noted above, this will need to be LIBGCCJIT_ABI_16 as I used
> LIBGCCJIT_ABI_15 for inline asm.
Fixed.
> 
> [...snip...]
> 
> > diff --git a/gcc/testsuite/jit.dg/test-reflection.c
> > b/gcc/testsuite/jit.dg/test-reflection.c
> > new file mode 100644
> > index 00000000000..b3cf2942f3a
> > --- /dev/null
> > +++ b/gcc/testsuite/jit.dg/test-reflection.c
> > @@ -0,0 +1,89 @@
> > +#include <stdlib.h>
> > +#include <stdio.h>
> > +
> > +#include "libgccjit.h"
> > +
> > +#include "harness.h"
> > +
> > +void
> > +create_code (gcc_jit_context *ctxt, void *user_data)
> > +{
> > +  /* Do nothing.  */
> > +}
> > +
> > +void
> > +verify_code (gcc_jit_context *ctxt, gcc_jit_result *result)
> > +{
> > +  /* Get the built-in functions.  */
> > +  gcc_jit_function *builtin_sin =
> > +    gcc_jit_context_get_builtin_function (ctxt, "sin");
> > +
> > +  CHECK_VALUE (gcc_jit_function_get_param_count(builtin_sin), 1);
> > +
> > +  gcc_jit_type *double_type =
> > +    gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_DOUBLE);
> > +  CHECK_VALUE (gcc_jit_function_get_return_type(builtin_sin),
> > double_type);
> > +  CHECK (!gcc_jit_type_is_integral(double_type));
> > +
> > +  gcc_jit_type *bool_type =
> > +    gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_BOOL);
> > +  CHECK (gcc_jit_type_is_bool(bool_type));
> > +  CHECK (!gcc_jit_type_is_integral(bool_type));
> > +
> > +  gcc_jit_type *aligned_bool_type =
> > +    gcc_jit_type_get_aligned(gcc_jit_context_get_type (ctxt,
> > GCC_JIT_TYPE_BOOL), 8);
> > +  CHECK (gcc_jit_type_is_bool(aligned_bool_type));
> > +  CHECK (bool_type != aligned_bool_type);
> > +  CHECK_VALUE (gcc_jit_type_unqualified(aligned_bool_type),
> > bool_type);
> > +
> > +  CHECK_VALUE
> > (gcc_jit_type_unqualified(gcc_jit_type_get_const(bool_type)),
> > bool_type);
> > +  CHECK_VALUE
> > (gcc_jit_type_unqualified(gcc_jit_type_get_volatile(bool_type)),
> > bool_type);
> > +
> > +  gcc_jit_type *int64 =
> > +    gcc_jit_context_get_int_type(ctxt, 8, 1);
> > +  CHECK (gcc_jit_type_is_integral(int64));
> > +  gcc_jit_type *uint64 =
> > +    gcc_jit_context_get_int_type(ctxt, 8, 0);
> > +  CHECK (gcc_jit_type_is_integral(uint64));
> > +  gcc_jit_type *int8 =
> > +    gcc_jit_context_get_int_type(ctxt, 1, 1);
> > +  CHECK (gcc_jit_type_is_integral(int8));
> > +  gcc_jit_type *uint8 =
> > +    gcc_jit_context_get_int_type(ctxt, 1, 0);
> > +  CHECK (gcc_jit_type_is_integral(uint8));
> > +
> > +  CHECK (!gcc_jit_type_is_vector(double_type));
> > +  gcc_jit_type *vec_type = gcc_jit_type_get_vector (double_type,
> > 4);
> > +  gcc_jit_vector_type *vector_type =
> > gcc_jit_type_is_vector(vec_type);
> > +  CHECK (vector_type);
> > +  CHECK (vec_type != double_type);
> > +  CHECK_VALUE (gcc_jit_vector_type_get_element_type(vector_type),
> > double_type);
> > +  CHECK_VALUE (gcc_jit_vector_type_get_num_units(vector_type), 4);
> > +
> > +  CHECK (!gcc_jit_type_is_pointer(double_type));
> > +  CHECK_VALUE
> > (gcc_jit_type_is_pointer(gcc_jit_type_get_pointer(double_type)),
> > double_type);
> > +
> > +  gcc_jit_type* params[2] = {int8, uint64};
> > +  gcc_jit_type *function_ptr_type =
> > gcc_jit_context_new_function_ptr_type(ctxt, NULL, int64, 2, params,
> > 0);
> > +  gcc_jit_function_type *function_type =
> > gcc_jit_type_is_function_ptr_type (function_ptr_type);
> > +  CHECK (function_type);
> > +  int param_count =
> > gcc_jit_function_type_get_param_count(function_type);
> > +  CHECK_VALUE (param_count, 2);
> > +  gcc_jit_type *return_type =
> > gcc_jit_function_type_get_return_type(function_type);
> > +  CHECK_VALUE (return_type, int64);
> > +  gcc_jit_type *param1 =
> > gcc_jit_function_type_get_param_type(function_type, 0);
> > +  CHECK_VALUE (param1, int8);
> > +  gcc_jit_type *param2 =
> > gcc_jit_function_type_get_param_type(function_type, 1);
> > +  CHECK_VALUE (param2, uint64);
> > +
> > +  gcc_jit_field *field1 = gcc_jit_context_new_field (ctxt, NULL,
> > uint64, "field1");
> > +  gcc_jit_field *field2 = gcc_jit_context_new_field (ctxt, NULL,
> > double_type, "field2");
> > +  gcc_jit_field *fields[2] = { field1, field2 };
> > +  gcc_jit_struct *struct_type = gcc_jit_context_new_struct_type
> > (ctxt, NULL, "testStruct", 2, fields);
> > +  CHECK_VALUE (gcc_jit_struct_get_field_count(struct_type), 2);
> > +  CHECK_VALUE (gcc_jit_struct_get_field(struct_type, 0), field1);
> > +  CHECK_VALUE (gcc_jit_struct_get_field(struct_type, 1), field2);
> > +  gcc_jit_struct *struct_ty =
> > gcc_jit_type_is_struct(gcc_jit_struct_as_type(struct_type));
> > +  CHECK_VALUE (struct_ty, struct_type);
> 
> 
> I think this is missing test coverage for the various
> gcc_jit_type_is_*
> entrypoints gracefully returning NULL when the type passed to them is
> wrong (e.g. a non-struct type passed to gcc_jit_type_is_struct, etc)

I added tests for those.

> 
> Hope this is constructive; sorry again about the delay in reviewing
> it.
> Dave
> 
> 


[-- Attachment #2: 0001-This-patch-add-some-reflection-functions-in-the-jit-.patch --]
[-- Type: text/x-patch, Size: 31148 bytes --]

From 6f2d37a67ad9ad72eaf3f17f4d20a5be5a093ac4 Mon Sep 17 00:00:00 2001
From: Antoni Boucher <bouanto@zoho.com>
Date: Sat, 1 Aug 2020 17:52:17 -0400
Subject: [PATCH] This patch add some reflection functions in the jit C api
 [PR96889]

2020-09-1  Antoni Boucher  <bouanto@zoho.com>

    gcc/jit/
            PR target/96889
            * docs/topics/compatibility.rst (LIBGCCJIT_ABI_16): New ABI tag.
            * docs/topics/functions.rst: Add documentation for the
            functions gcc_jit_function_get_return_type and
            gcc_jit_function_get_param_count
            * docs/topics/types.rst: Add documentation for the functions
            gcc_jit_function_type_get_return_type,
            gcc_jit_function_type_get_param_count,
            gcc_jit_function_type_get_param_type,
            gcc_jit_type_unqualified, gcc_jit_type_is_array,
            gcc_jit_type_is_bool,
            gcc_jit_type_is_function_ptr_type,
            gcc_jit_type_is_integral, gcc_jit_type_is_pointer,
            gcc_jit_type_is_vector,
            gcc_jit_vector_type_get_element_type,
            gcc_jit_vector_type_get_num_units,
            gcc_jit_struct_get_field, gcc_jit_type_is_struct,
            and gcc_jit_struct_get_field_count
            * libgccjit.c:
            (gcc_jit_function_get_return_type, gcc_jit_function_get_param_count,
            gcc_jit_function_type_get_return_type,
            gcc_jit_function_type_get_param_count,
            gcc_jit_function_type_get_param_type, gcc_jit_type_unqualified,
            gcc_jit_type_is_array, gcc_jit_type_is_bool,
            gcc_jit_type_is_function_ptr_type, gcc_jit_type_is_integral,
            gcc_jit_type_is_pointer, gcc_jit_type_is_vector,
            gcc_jit_vector_type_get_element_type,
            gcc_jit_vector_type_get_num_units, gcc_jit_struct_get_field,
            gcc_jit_type_is_struct, gcc_jit_struct_get_field_count): New
            functions.
            (struct gcc_jit_function_type, struct gcc_jit_vector_type):
            New types.
            * libgccjit.h:
            (gcc_jit_function_get_return_type, gcc_jit_function_get_param_count,
            gcc_jit_function_type_get_return_type,
            gcc_jit_function_type_get_param_count,
            gcc_jit_function_type_get_param_type, gcc_jit_type_unqualified,
            gcc_jit_type_is_array, gcc_jit_type_is_bool,
            gcc_jit_type_is_function_ptr_type, gcc_jit_type_is_integral,
            gcc_jit_type_is_pointer, gcc_jit_type_is_vector,
            gcc_jit_vector_type_get_element_type,
            gcc_jit_vector_type_get_num_units, gcc_jit_struct_get_field,
            gcc_jit_type_is_struct, gcc_jit_struct_get_field_count): New
            function declarations.
            (struct gcc_jit_function_type, struct gcc_jit_vector_type):
            New types.
            * jit-recording.h: New functions (is_struct and is_vector)
            * libgccjit.map (LIBGCCJIT_ABI_16): New ABI tag.

    gcc/testsuite/
            PR target/96889
            * jit.dg/all-non-failing-tests.h: Add test-reflection.c.
            * jit.dg/test-reflection.c: New test.
---
 gcc/jit/docs/topics/compatibility.rst        |  43 +++-
 gcc/jit/docs/topics/functions.rst            |  26 ++
 gcc/jit/docs/topics/types.rst                | 122 +++++++++
 gcc/jit/jit-recording.h                      |   7 +
 gcc/jit/libgccjit.c                          | 256 +++++++++++++++++++
 gcc/jit/libgccjit.h                          |  89 +++++++
 gcc/jit/libgccjit.map                        |  21 ++
 gcc/testsuite/jit.dg/all-non-failing-tests.h |  10 +
 gcc/testsuite/jit.dg/test-reflection.c       |  95 +++++++
 9 files changed, 668 insertions(+), 1 deletion(-)
 create mode 100644 gcc/testsuite/jit.dg/test-reflection.c

diff --git a/gcc/jit/docs/topics/compatibility.rst b/gcc/jit/docs/topics/compatibility.rst
index 239b6aa1a92..cec40ca508c 100644
--- a/gcc/jit/docs/topics/compatibility.rst
+++ b/gcc/jit/docs/topics/compatibility.rst
@@ -230,7 +230,7 @@ entrypoints:
 .. _LIBGCCJIT_ABI_15:
 
 ``LIBGCCJIT_ABI_15``
------------------------
+--------------------
 ``LIBGCCJIT_ABI_15`` covers the addition of API entrypoints for directly
 embedding assembler instructions:
 
@@ -243,3 +243,44 @@ embedding assembler instructions:
   * :func:`gcc_jit_extended_asm_add_input_operand`
   * :func:`gcc_jit_extended_asm_add_clobber`
   * :func:`gcc_jit_context_add_top_level_asm`
+
+.. _LIBGCCJIT_ABI_16:
+
+``LIBGCCJIT_ABI_16``
+--------------------
+``LIBGCCJIT_ABI_16`` covers the addition of reflection functions via API
+entrypoints:
+
+  * :func:`gcc_jit_function_get_return_type`
+
+  * :func:`gcc_jit_function_get_param_count`
+
+  * :func:`gcc_jit_type_is_array`
+
+  * :func:`gcc_jit_type_is_bool`
+
+  * :func:`gcc_jit_type_is_integral`
+
+  * :func:`gcc_jit_type_is_pointer`
+
+  * :func:`gcc_jit_type_is_struct`
+
+  * :func:`gcc_jit_type_is_vector`
+
+  * :func:`gcc_jit_type_unqualified`
+
+  * :func:`gcc_jit_type_is_function_ptr_type`
+
+  * :func:`gcc_jit_function_type_get_return_type`
+
+  * :func:`gcc_jit_function_type_get_param_count`
+
+  * :func:`gcc_jit_function_type_get_param_type`
+
+  * :func:`gcc_jit_vector_type_get_num_units`
+
+  * :func:`gcc_jit_vector_type_get_element_type`
+
+  * :func:`gcc_jit_struct_get_field`
+
+  * :func:`gcc_jit_struct_get_field_count`
diff --git a/gcc/jit/docs/topics/functions.rst b/gcc/jit/docs/topics/functions.rst
index b2d9239aa0a..950da4e5a76 100644
--- a/gcc/jit/docs/topics/functions.rst
+++ b/gcc/jit/docs/topics/functions.rst
@@ -171,6 +171,32 @@ Functions
    underlying string, so it is valid to pass in a pointer to an on-stack
    buffer.
 
+.. function::  ssize_t \
+               gcc_jit_function_get_param_count (gcc_jit_function *func)
+
+   Get the number of parameters of the function.
+
+.. function::  gcc_jit_type *\
+               gcc_jit_function_get_return_type (gcc_jit_function *func)
+
+   Get the return type of the function.
+
+   The API entrypoints relating to getting info about parameters and return
+   types:
+
+      * :c:func:`gcc_jit_function_get_return_type`
+
+      * :c:func:`gcc_jit_function_get_param_count`
+
+   were added in :ref:`LIBGCCJIT_ABI_15`; you can test for their presence
+   using
+
+   .. code-block:: c
+
+      #ifdef LIBGCCJIT_HAVE_REFLECTION
+
+   .. type:: gcc_jit_case
+
 Blocks
 ------
 .. type:: gcc_jit_block
diff --git a/gcc/jit/docs/topics/types.rst b/gcc/jit/docs/topics/types.rst
index 831f11b679a..73cdca11c3b 100644
--- a/gcc/jit/docs/topics/types.rst
+++ b/gcc/jit/docs/topics/types.rst
@@ -345,3 +345,125 @@ Function pointer types
 
 Function pointer types can be created using
 :c:func:`gcc_jit_context_new_function_ptr_type`.
+
+Reflection API
+--------------
+
+.. function::  gcc_jit_type *\
+               gcc_jit_type_is_array (gcc_jit_type *type)
+
+     Get the element type of an array type or NULL if it's not an array.
+
+.. function::  int\
+               gcc_jit_type_is_bool (gcc_jit_type *type)
+
+     Return non-zero if the type is a bool.
+
+.. function::  gcc_jit_function_type *\
+               gcc_jit_type_is_function_ptr_type (gcc_jit_type *type)
+
+     Return the function type if it is one or NULL.
+
+.. function::  gcc_jit_type *\
+               gcc_jit_function_type_get_return_type (gcc_jit_function_type *function_type)
+
+     Given a function type, return its return type.
+
+.. function::  ssize_t\
+               gcc_jit_function_type_get_param_count (gcc_jit_function_type *function_type)
+
+     Given a function type, return its number of parameters.
+
+.. function::  gcc_jit_type *\
+               gcc_jit_function_type_get_param_type (gcc_jit_function_type *function_type,
+                                                     size_t index)
+
+     Given a function type, return the type of the specified parameter.
+
+.. function::  int\
+               gcc_jit_type_is_integral (gcc_jit_type *type)
+
+     Return non-zero if the type is an integral.
+
+.. function::  gcc_jit_type *\
+               gcc_jit_type_is_pointer (gcc_jit_type *type)
+
+     Return the type pointed by the pointer type or NULL if it's not a pointer.
+
+.. function::  gcc_jit_vector_type *\
+               gcc_jit_type_is_vector (gcc_jit_type *type)
+
+     Given a type, return a dynamic cast to a vector type or NULL.
+
+.. function::  gcc_jit_struct *\
+               gcc_jit_type_is_struct (gcc_jit_type *type)
+
+     Given a type, return a dynamic cast to a struct type or NULL.
+
+.. function::  ssize_t\
+               gcc_jit_vector_type_get_num_units (gcc_jit_vector_type *vector_type)
+
+     Given a vector type, return the number of units it contains.
+
+.. function::  gcc_jit_type *\
+               gcc_jit_vector_type_get_element_type (gcc_jit_vector_type * vector_type)
+
+     Given a vector type, return the type of its elements.
+
+.. function::  gcc_jit_type *\
+               gcc_jit_type_unqualified (gcc_jit_type *type)
+
+     Given a type, return the unqualified type, removing "const", "volatile" and
+     alignment qualifiers.
+
+.. function::  gcc_jit_field *\
+               gcc_jit_struct_get_field (gcc_jit_struct *struct_type,
+                                         size_t index)
+
+     Get a struct field by index.
+
+.. function::  ssize_t\
+               gcc_jit_struct_get_field_count (gcc_jit_struct *struct_type)
+
+     Get the number of fields in the struct.
+
+   The API entrypoints related to the reflection API:
+
+      * :c:func:`gcc_jit_function_type_get_return_type`
+
+      * :c:func:`gcc_jit_function_type_get_param_count`
+
+      * :c:func:`gcc_jit_function_type_get_param_type`
+
+      * :c:func:`gcc_jit_type_unqualified`
+
+      * :c:func:`gcc_jit_type_is_array`
+
+      * :c:func:`gcc_jit_type_is_bool`
+
+      * :c:func:`gcc_jit_type_is_function_ptr_type`
+
+      * :c:func:`gcc_jit_type_is_integral`
+
+      * :c:func:`gcc_jit_type_is_pointer`
+
+      * :c:func:`gcc_jit_type_is_vector`
+
+      * :c:func:`gcc_jit_vector_type_get_element_type`
+
+      * :c:func:`gcc_jit_vector_type_get_num_units`
+
+      * :c:func:`gcc_jit_struct_get_field`
+
+      * :c:func:`gcc_jit_type_is_struct`
+
+      * :c:func:`gcc_jit_struct_get_field_count`
+
+   were added in :ref:`LIBGCCJIT_ABI_15`; you can test for their presence
+   using
+
+   .. code-block:: c
+
+      #ifdef LIBGCCJIT_HAVE_REFLECTION
+
+   .. type:: gcc_jit_case
diff --git a/gcc/jit/jit-recording.h b/gcc/jit/jit-recording.h
index 03fa1160cf0..4a994fe7094 100644
--- a/gcc/jit/jit-recording.h
+++ b/gcc/jit/jit-recording.h
@@ -546,7 +546,9 @@ public:
   virtual bool is_bool () const = 0;
   virtual type *is_pointer () = 0;
   virtual type *is_array () = 0;
+  virtual struct_ *is_struct () { return NULL; }
   virtual bool is_void () const { return false; }
+  virtual vector_type *is_vector () { return NULL; }
   virtual bool has_known_size () const { return true; }
 
   bool is_numeric () const
@@ -663,6 +665,7 @@ public:
   bool is_bool () const FINAL OVERRIDE { return m_other_type->is_bool (); }
   type *is_pointer () FINAL OVERRIDE { return m_other_type->is_pointer (); }
   type *is_array () FINAL OVERRIDE { return m_other_type->is_array (); }
+  struct_ *is_struct () FINAL OVERRIDE { return m_other_type->is_struct (); }
 
 protected:
   type *m_other_type;
@@ -745,6 +748,8 @@ public:
 
   void replay_into (replayer *) FINAL OVERRIDE;
 
+  vector_type *is_vector () FINAL OVERRIDE { return this; }
+
 private:
   string * make_debug_string () FINAL OVERRIDE;
   void write_reproducer (reproducer &r) FINAL OVERRIDE;
@@ -951,6 +956,8 @@ public:
 
   const char *access_as_type (reproducer &r) FINAL OVERRIDE;
 
+  struct_ *is_struct () FINAL OVERRIDE { return this; }
+
 private:
   string * make_debug_string () FINAL OVERRIDE;
   void write_reproducer (reproducer &r) FINAL OVERRIDE;
diff --git a/gcc/jit/libgccjit.c b/gcc/jit/libgccjit.c
index 0cc650f9810..b0cbd3a2b6a 100644
--- a/gcc/jit/libgccjit.c
+++ b/gcc/jit/libgccjit.c
@@ -60,6 +60,14 @@ struct gcc_jit_struct : public gcc::jit::recording::struct_
 {
 };
 
+struct gcc_jit_function_type : public gcc::jit::recording::function_type
+{
+};
+
+struct gcc_jit_vector_type : public gcc::jit::recording::vector_type
+{
+};
+
 struct gcc_jit_field : public gcc::jit::recording::field
 {
 };
@@ -515,6 +523,194 @@ gcc_jit_type_get_volatile (gcc_jit_type *type)
   return (gcc_jit_type *)type->get_volatile ();
 }
 
+/* Public entrypoint.  See description in libgccjit.h.
+
+   After error-checking, the real work is done by the
+   gcc::jit::recording::type::is_array method, in
+   jit-recording.c.  */
+
+gcc_jit_type *
+gcc_jit_type_is_array (gcc_jit_type *type)
+{
+  RETURN_NULL_IF_FAIL (type, NULL, NULL, "NULL type");
+
+  return (gcc_jit_type *)type->is_array ();
+}
+
+/* Public entrypoint.  See description in libgccjit.h.
+
+   After error-checking, the real work is done by the
+   gcc::jit::recording::type::is_bool method, in
+   jit-recording.c.  */
+
+int
+gcc_jit_type_is_bool (gcc_jit_type *type)
+{
+  RETURN_VAL_IF_FAIL (type, FALSE, NULL, NULL, "NULL type");
+
+  return type->is_bool ();
+}
+
+/* Public entrypoint.  See description in libgccjit.h.
+
+   After error-checking, the real work is done by the
+   gcc::jit::recording::type::is_pointer method, in
+   jit-recording.c.  */
+
+gcc_jit_type *
+gcc_jit_type_is_pointer (gcc_jit_type *type)
+{
+  RETURN_NULL_IF_FAIL (type, NULL, NULL, "NULL type");
+
+  return (gcc_jit_type *)type->is_pointer ();
+}
+
+/* Public entrypoint.  See description in libgccjit.h.
+
+   After error-checking, the real work is done by the
+   gcc::jit::recording::type::is_int method, in
+   jit-recording.c.  */
+
+int
+gcc_jit_type_is_integral (gcc_jit_type *type)
+{
+  RETURN_VAL_IF_FAIL (type, FALSE, NULL, NULL, "NULL type");
+
+  return type->is_int ();
+}
+
+/* Public entrypoint.  See description in libgccjit.h.
+
+   After error-checking, the real work is done by the
+   gcc::jit::recording::type::is_vector method, in
+   jit-recording.c.  */
+
+gcc_jit_vector_type *
+gcc_jit_type_is_vector (gcc_jit_type *type)
+{
+  RETURN_NULL_IF_FAIL (type, NULL, NULL, "NULL type");
+  gcc::jit::recording::vector_type *vector_type = type->is_vector ();
+  return (gcc_jit_vector_type *)vector_type;
+}
+
+/* Public entrypoint.  See description in libgccjit.h.
+
+   After error-checking, the real work is done by the
+   gcc::jit::recording::type::is_struct method, in
+   jit-recording.c.  */
+
+gcc_jit_struct *
+gcc_jit_type_is_struct (gcc_jit_type *type)
+{
+  RETURN_NULL_IF_FAIL (type, NULL, NULL, "NULL type");
+  gcc::jit::recording::struct_ *struct_type = type->is_struct ();
+  return (gcc_jit_struct *)struct_type;
+}
+
+/* Public entrypoint.  See description in libgccjit.h.
+
+   After error-checking, the real work is done by the
+   gcc::jit::recording::vector_type::get_num_units method, in
+   jit-recording.c.  */
+
+ssize_t
+gcc_jit_vector_type_get_num_units (gcc_jit_vector_type *vector_type)
+{
+  RETURN_VAL_IF_FAIL (vector_type, -1, NULL, NULL, "NULL vector_type");
+  return vector_type->get_num_units ();
+}
+
+/* Public entrypoint.  See description in libgccjit.h.
+
+   After error-checking, the real work is done by the
+   gcc::jit::recording::vector_type::get_element_type method, in
+   jit-recording.c.  */
+
+gcc_jit_type *
+gcc_jit_vector_type_get_element_type (gcc_jit_vector_type *vector_type)
+{
+  RETURN_NULL_IF_FAIL (vector_type, NULL, NULL, "NULL vector_type");
+  return (gcc_jit_type *)vector_type->get_element_type ();
+}
+
+/* Public entrypoint.  See description in libgccjit.h.
+
+   After error-checking, the real work is done by the
+   gcc::jit::recording::type::unqualified method, in
+   jit-recording.c.  */
+
+gcc_jit_type *
+gcc_jit_type_unqualified (gcc_jit_type *type)
+{
+  RETURN_NULL_IF_FAIL (type, NULL, NULL, "NULL type");
+
+  return (gcc_jit_type *)type->unqualified ();
+}
+
+/* Public entrypoint.  See description in libgccjit.h.
+
+   After error-checking, the real work is done by the
+   gcc::jit::recording::type::dyn_cast_function_type method, in
+   jit-recording.c.  */
+
+gcc_jit_function_type *
+gcc_jit_type_is_function_ptr_type (gcc_jit_type *type)
+{
+  RETURN_NULL_IF_FAIL (type, NULL, NULL, "NULL type");
+  gcc::jit::recording::type *func_ptr_type = type->dereference ();
+  RETURN_NULL_IF_FAIL (func_ptr_type, NULL, NULL, "NULL type");
+
+  return (gcc_jit_function_type *)func_ptr_type->dyn_cast_function_type ();
+}
+
+/* Public entrypoint.  See description in libgccjit.h.
+
+   After error-checking, the real work is done by the
+   gcc::jit::recording::function_type::get_return_type method, in
+   jit-recording.c.  */
+
+gcc_jit_type *
+gcc_jit_function_type_get_return_type (gcc_jit_function_type *function_type)
+{
+  RETURN_NULL_IF_FAIL (function_type, NULL, NULL, "NULL function_type");
+  return (gcc_jit_type *)function_type->get_return_type ();
+}
+
+/* Public entrypoint.  See description in libgccjit.h.
+
+   After error-checking, the real work is done by the
+   gcc::jit::recording::function_type::get_param_types method, in
+   jit-recording.c.  */
+
+ssize_t
+gcc_jit_function_type_get_param_count (gcc_jit_function_type *function_type)
+{
+  RETURN_VAL_IF_FAIL (function_type, -1, NULL, NULL, "NULL function_type");
+  return function_type->get_param_types ().length ();
+}
+
+/* Public entrypoint.  See description in libgccjit.h.
+
+   After error-checking, the real work is done by the
+   gcc::jit::recording::function_type::get_param_types method, in
+   jit-recording.c.  */
+
+gcc_jit_type *
+gcc_jit_function_type_get_param_type (gcc_jit_function_type *function_type,
+				size_t index)
+{
+  RETURN_NULL_IF_FAIL (function_type, NULL, NULL, "NULL function_type");
+  size_t num_params = function_type->get_param_types ().length ();
+  gcc::jit::recording::context *ctxt = function_type->m_ctxt;
+  RETURN_NULL_IF_FAIL_PRINTF3 (index < num_params,
+			       ctxt, NULL,
+			       "index of %ld is too large (%s has %ld params)",
+			       index,
+			       function_type->get_debug_string (),
+			       num_params);
+  return (gcc_jit_type *)function_type->get_param_types ()[index];
+}
+
 /* Public entrypoint.  See description in libgccjit.h.
 
    After error-checking, the real work is done by the
@@ -736,6 +932,37 @@ gcc_jit_struct_set_fields (gcc_jit_struct *struct_type,
 			   (gcc::jit::recording::field **)fields);
 }
 
+
+/* Public entrypoint.  See description in libgccjit.h.
+
+   After error-checking, the real work is done by the
+   gcc::jit::recording::fields::get_field method in
+   jit-recording.c.  */
+extern gcc_jit_field *
+gcc_jit_struct_get_field (gcc_jit_struct *struct_type,
+			   size_t index)
+{
+  RETURN_NULL_IF_FAIL (struct_type, NULL, NULL, "NULL struct type");
+  RETURN_NULL_IF_FAIL (struct_type->get_fields (), NULL, NULL,
+				"NULL struct fields");
+  RETURN_NULL_IF_FAIL ((int) index < struct_type->get_fields ()->length (),
+				NULL, NULL, "NULL struct type");
+  return (gcc_jit_field *)struct_type->get_fields ()->get_field (index);
+}
+
+/* Public entrypoint.  See description in libgccjit.h.
+
+   After error-checking, this calls the trivial
+   gcc::jit::recording::struct_::get_fields method in
+   jit-recording.h.  */
+
+ssize_t
+gcc_jit_struct_get_field_count (gcc_jit_struct *struct_type)
+{
+  RETURN_VAL_IF_FAIL (struct_type, -1, NULL, NULL, "NULL struct type");
+  return struct_type->get_fields ()->length ();
+}
+
 /* Public entrypoint.  See description in libgccjit.h.
 
    After error-checking, the real work is done by the
@@ -1017,6 +1244,35 @@ gcc_jit_function_get_param (gcc_jit_function *func, int index)
   return static_cast <gcc_jit_param *> (func->get_param (index));
 }
 
+/* Public entrypoint.  See description in libgccjit.h.
+
+   After error-checking, the real work is done by the
+   gcc::jit::recording::function::get_params method, in
+   jit-recording.h.
+  */
+
+ssize_t
+gcc_jit_function_get_param_count (gcc_jit_function *func)
+{
+  RETURN_VAL_IF_FAIL (func, -1, NULL, NULL, "NULL function");
+  gcc::jit::recording::context *ctxt = func->m_ctxt;
+  JIT_LOG_FUNC (ctxt->get_logger ());
+  return func->get_params ().length ();
+}
+
+/* Public entrypoint.  See description in libgccjit.h.
+
+   After error-checking, the real work is done by the
+   gcc::jit::recording::function::get_return_type method, in
+   jit-recording.h.  */
+
+gcc_jit_type *
+gcc_jit_function_get_return_type (gcc_jit_function *func)
+{
+    RETURN_NULL_IF_FAIL (func, NULL, NULL, "NULL function_type");
+    return (gcc_jit_type *)func->get_return_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 5c722c2c57f..1e5c5c169cb 100644
--- a/gcc/jit/libgccjit.h
+++ b/gcc/jit/libgccjit.h
@@ -61,6 +61,8 @@ typedef struct gcc_jit_result gcc_jit_result;
 	 +- gcc_jit_location
 	 +- gcc_jit_type
 	    +- gcc_jit_struct
+	    +- gcc_jit_function_type
+	    +- gcc_jit_vector_type
 	 +- gcc_jit_field
 	 +- gcc_jit_function
 	 +- gcc_jit_block
@@ -97,6 +99,12 @@ typedef struct gcc_jit_field gcc_jit_field;
    the layout for, or an opaque type.  */
 typedef struct gcc_jit_struct gcc_jit_struct;
 
+/* A gcc_jit_function_type encapsulates a function type.  */
+typedef struct gcc_jit_function_type gcc_jit_function_type;
+
+/* A gcc_jit_vector_type encapsulates a vector type.  */
+typedef struct gcc_jit_vector_type gcc_jit_vector_type;
+
 /* A gcc_jit_function encapsulates a function: either one that you're
    creating yourself, or a reference to one that you're dynamically
    linking to within the rest of the process.  */
@@ -654,6 +662,15 @@ gcc_jit_struct_set_fields (gcc_jit_struct *struct_type,
 			   int num_fields,
 			   gcc_jit_field **fields);
 
+/* Get a field by index.  */
+extern gcc_jit_field *
+gcc_jit_struct_get_field (gcc_jit_struct *struct_type,
+			   size_t index);
+
+/* Get the number of fields.  */
+extern ssize_t
+gcc_jit_struct_get_field_count (gcc_jit_struct *struct_type);
+
 /* Unions work similarly to structs.  */
 extern gcc_jit_type *
 gcc_jit_context_new_union_type (gcc_jit_context *ctxt,
@@ -1621,6 +1638,78 @@ gcc_jit_context_add_top_level_asm (gcc_jit_context *ctxt,
 				   gcc_jit_location *loc,
 				   const char *asm_stmts);
 
+#define LIBGCCJIT_HAVE_REFLECTION
+
+/* Reflection functions to get the number of parameters, return type of
+   a function and whether a type is a bool from the C API.
+
+   This API entrypoint was added in LIBGCCJIT_ABI_15; you can test for its
+   presence using
+     #ifdef LIBGCCJIT_HAVE_REFLECTION
+*/
+/* Get the return type of a function.  */
+extern gcc_jit_type *
+gcc_jit_function_get_return_type (gcc_jit_function *func);
+
+/* Get the number of params of a function.  */
+extern ssize_t
+gcc_jit_function_get_param_count (gcc_jit_function *func);
+
+/* Get the element type of an array type or NULL if it's not an array.  */
+extern gcc_jit_type *
+gcc_jit_type_is_array (gcc_jit_type *type);
+
+/* Return non-zero if the type is a bool.  */
+extern int
+gcc_jit_type_is_bool (gcc_jit_type *type);
+
+/* Return the function type if it is one or NULL.  */
+extern gcc_jit_function_type *
+gcc_jit_type_is_function_ptr_type (gcc_jit_type *type);
+
+/* Given a function type, return its return type.  */
+extern gcc_jit_type *
+gcc_jit_function_type_get_return_type (gcc_jit_function_type *function_type);
+
+/* Given a function type, return its number of parameters.  */
+extern ssize_t
+gcc_jit_function_type_get_param_count (gcc_jit_function_type *function_type);
+
+/* Given a function type, return the type of the specified parameter.  */
+extern gcc_jit_type *
+gcc_jit_function_type_get_param_type (gcc_jit_function_type *function_type,
+				size_t index);
+
+/* Return non-zero if the type is an integral.  */
+extern int
+gcc_jit_type_is_integral (gcc_jit_type *type);
+
+/* Return the type pointed by the pointer type or NULL if it's not a
+ * pointer.  */
+extern gcc_jit_type *
+gcc_jit_type_is_pointer (gcc_jit_type *type);
+
+/* Given a type, return a dynamic cast to a vector type or NULL.  */
+extern gcc_jit_vector_type *
+gcc_jit_type_is_vector (gcc_jit_type *type);
+
+/* Given a type, return a dynamic cast to a struct type or NULL.  */
+extern gcc_jit_struct *
+gcc_jit_type_is_struct (gcc_jit_type *type);
+
+/* Given a vector type, return the number of units it contains.  */
+extern ssize_t
+gcc_jit_vector_type_get_num_units (gcc_jit_vector_type *vector_type);
+
+/* Given a vector type, return the type of its elements.  */
+extern gcc_jit_type *
+gcc_jit_vector_type_get_element_type (gcc_jit_vector_type *vector_type);
+
+/* Given a type, return the unqualified type, removing "const", "volatile"
+ * and alignment qualifiers.  */
+extern gcc_jit_type *
+gcc_jit_type_unqualified (gcc_jit_type *type);
+
 #ifdef __cplusplus
 }
 #endif /* __cplusplus */
diff --git a/gcc/jit/libgccjit.map b/gcc/jit/libgccjit.map
index 337ea6c7fe4..84358763cd6 100644
--- a/gcc/jit/libgccjit.map
+++ b/gcc/jit/libgccjit.map
@@ -205,3 +205,24 @@ LIBGCCJIT_ABI_15 {
     gcc_jit_extended_asm_add_clobber;
     gcc_jit_context_add_top_level_asm;
 } LIBGCCJIT_ABI_14;
+
+LIBGCCJIT_ABI_16 {
+  global:
+    gcc_jit_function_get_return_type;
+    gcc_jit_function_get_param_count;
+    gcc_jit_function_type_get_return_type;
+    gcc_jit_function_type_get_param_count;
+    gcc_jit_function_type_get_param_type;
+    gcc_jit_type_unqualified;
+    gcc_jit_type_is_array;
+    gcc_jit_type_is_bool;
+    gcc_jit_type_is_function_ptr_type;
+    gcc_jit_type_is_integral;
+    gcc_jit_type_is_pointer;
+    gcc_jit_type_is_vector;
+    gcc_jit_vector_type_get_element_type;
+    gcc_jit_vector_type_get_num_units;
+    gcc_jit_struct_get_field;
+    gcc_jit_type_is_struct;
+    gcc_jit_struct_get_field_count;
+} LIBGCCJIT_ABI_15;
diff --git a/gcc/testsuite/jit.dg/all-non-failing-tests.h b/gcc/testsuite/jit.dg/all-non-failing-tests.h
index 4202eb7798b..a269144d2df 100644
--- a/gcc/testsuite/jit.dg/all-non-failing-tests.h
+++ b/gcc/testsuite/jit.dg/all-non-failing-tests.h
@@ -258,6 +258,13 @@
 #undef create_code
 #undef verify_code
 
+/* test-reflection.c */
+#define create_code create_code_reflection
+#define verify_code verify_code_reflection
+#include "test-reflection.c"
+#undef create_code
+#undef verify_code
+
 /* test-string-literal.c */
 #define create_code create_code_string_literal
 #define verify_code verify_code_string_literal
@@ -424,6 +431,9 @@ const struct testcase testcases[] = {
   {"reading_struct ",
    create_code_reading_struct ,
    verify_code_reading_struct },
+  {"reflection",
+   create_code_reflection ,
+   verify_code_reflection },
   {"string_literal",
    create_code_string_literal,
    verify_code_string_literal},
diff --git a/gcc/testsuite/jit.dg/test-reflection.c b/gcc/testsuite/jit.dg/test-reflection.c
new file mode 100644
index 00000000000..46ab2c3e887
--- /dev/null
+++ b/gcc/testsuite/jit.dg/test-reflection.c
@@ -0,0 +1,95 @@
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "libgccjit.h"
+
+#include "harness.h"
+
+void
+create_code (gcc_jit_context *ctxt, void *user_data)
+{
+  /* Do nothing.  */
+}
+
+void
+verify_code (gcc_jit_context *ctxt, gcc_jit_result *result)
+{
+  /* Get the built-in functions.  */
+  gcc_jit_function *builtin_sin =
+    gcc_jit_context_get_builtin_function (ctxt, "sin");
+
+  CHECK_VALUE (gcc_jit_function_get_param_count(builtin_sin), 1);
+
+  gcc_jit_type *double_type =
+    gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_DOUBLE);
+  CHECK_VALUE (gcc_jit_function_get_return_type(builtin_sin), double_type);
+  CHECK (!gcc_jit_type_is_integral(double_type));
+
+  gcc_jit_type *bool_type =
+    gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_BOOL);
+  CHECK (gcc_jit_type_is_bool(bool_type));
+  CHECK (!gcc_jit_type_is_integral(bool_type));
+
+  gcc_jit_type *aligned_bool_type =
+    gcc_jit_type_get_aligned(gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_BOOL), 8);
+  CHECK (gcc_jit_type_is_bool(aligned_bool_type));
+  CHECK (bool_type != aligned_bool_type);
+  CHECK_VALUE (gcc_jit_type_unqualified(aligned_bool_type), bool_type);
+
+  CHECK_VALUE (gcc_jit_type_unqualified(gcc_jit_type_get_const(bool_type)), bool_type);
+  CHECK_VALUE (gcc_jit_type_unqualified(gcc_jit_type_get_volatile(bool_type)), bool_type);
+
+  gcc_jit_type *int64 =
+    gcc_jit_context_get_int_type(ctxt, 8, 1);
+  CHECK (gcc_jit_type_is_integral(int64));
+  gcc_jit_type *uint64 =
+    gcc_jit_context_get_int_type(ctxt, 8, 0);
+  CHECK (gcc_jit_type_is_integral(uint64));
+  gcc_jit_type *int8 =
+    gcc_jit_context_get_int_type(ctxt, 1, 1);
+  CHECK (gcc_jit_type_is_integral(int8));
+  gcc_jit_type *uint8 =
+    gcc_jit_context_get_int_type(ctxt, 1, 0);
+  CHECK (gcc_jit_type_is_integral(uint8));
+
+  CHECK (!gcc_jit_type_is_vector(double_type));
+  gcc_jit_type *vec_type = gcc_jit_type_get_vector (double_type, 4);
+  gcc_jit_vector_type *vector_type = gcc_jit_type_is_vector(vec_type);
+  CHECK (vector_type);
+  CHECK (vec_type != double_type);
+  CHECK_VALUE (gcc_jit_vector_type_get_element_type(vector_type), double_type);
+  CHECK_VALUE (gcc_jit_vector_type_get_num_units(vector_type), 4);
+
+  CHECK (!gcc_jit_type_is_pointer(double_type));
+  CHECK_VALUE (gcc_jit_type_is_pointer(gcc_jit_type_get_pointer(double_type)), double_type);
+
+  gcc_jit_type* params[2] = {int8, uint64};
+  gcc_jit_type *function_ptr_type = gcc_jit_context_new_function_ptr_type(ctxt, NULL, int64, 2, params, 0);
+  CHECK (!gcc_jit_type_is_function_ptr_type (int64));
+  gcc_jit_function_type *function_type = gcc_jit_type_is_function_ptr_type (function_ptr_type);
+  CHECK (function_type);
+  int param_count = gcc_jit_function_type_get_param_count(function_type);
+  CHECK_VALUE (param_count, 2);
+  gcc_jit_type *return_type = gcc_jit_function_type_get_return_type(function_type);
+  CHECK_VALUE (return_type, int64);
+  gcc_jit_type *param1 = gcc_jit_function_type_get_param_type(function_type, 0);
+  CHECK_VALUE (param1, int8);
+  gcc_jit_type *param2 = gcc_jit_function_type_get_param_type(function_type, 1);
+  CHECK_VALUE (param2, uint64);
+
+  gcc_jit_field *field1 = gcc_jit_context_new_field (ctxt, NULL, uint64, "field1");
+  gcc_jit_field *field2 = gcc_jit_context_new_field (ctxt, NULL, double_type, "field2");
+  gcc_jit_field *fields[2] = { field1, field2 };
+  gcc_jit_struct *struct_type = gcc_jit_context_new_struct_type (ctxt, NULL, "testStruct", 2, fields);
+  CHECK_VALUE (gcc_jit_struct_get_field_count(struct_type), 2);
+  CHECK_VALUE (gcc_jit_struct_get_field(struct_type, 0), field1);
+  CHECK_VALUE (gcc_jit_struct_get_field(struct_type, 1), field2);
+  CHECK (!gcc_jit_type_is_struct(double_type));
+  gcc_jit_struct *struct_ty = gcc_jit_type_is_struct(gcc_jit_struct_as_type(struct_type));
+  CHECK_VALUE (struct_ty, struct_type);
+
+  CHECK (!gcc_jit_type_is_array(double_type));
+  gcc_jit_type* array_type = gcc_jit_context_new_array_type(ctxt, NULL, double_type, 1);
+  CHECK_VALUE (gcc_jit_type_is_array(array_type), double_type);
+}
+
-- 
2.31.1


^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re: [PATCH] libgccjit: add some reflection functions in the jit C api
  2021-05-13 21:30               ` David Malcolm
  2021-05-14  2:11                 ` Antoni Boucher
@ 2021-05-26  0:19                 ` Antoni Boucher
  2021-05-27 22:19                   ` David Malcolm
  1 sibling, 1 reply; 35+ messages in thread
From: Antoni Boucher @ 2021-05-26  0:19 UTC (permalink / raw)
  To: David Malcolm; +Cc: Andrea Corallo, Antoni Boucher via Jit, gcc-patches

@David: PING

As far as I know, the only remaining question is about using `ssize_t`
for the return type of some functions.
Here's why I use this type:

That seemed off to return NULL for the functions returning a 
size_t to indicate an error. So I changed it to return -1 (and return
type to ssize_t). Is that the proper way to indicate an error?

Once I know the answer for this error handling question, I'll fix the
types.

Thanks!

Le jeudi 13 mai 2021 à 17:30 -0400, David Malcolm a écrit :
> On Tue, 2020-11-03 at 17:13 -0500, Antoni Boucher wrote:
> > I was missing a check in gcc_jit_struct_get_field, I added it in this
> > new patch.
> > 
> 
> Sorry about the long delay in reviewing this patch.
> 
> The main high-level points are:
> - currently the get_*_count functions return "ssize_t" - why?  Only
> unsigned values are meaningful; shouldn't they return "size_t" instead?
> 
> - the various "lookup by index" functions take "int" i.e. signed, but
> only >= 0 is meaningful.  I think it makes sense to make them take
> size_t instead.
> 
> Sorry if we covered that before in the review, it's been a while.
> 
> Various nitpicks inline below...
> 
> [...snip...]
>  
> > diff --git a/gcc/jit/docs/topics/compatibility.rst
> > b/gcc/jit/docs/topics/compatibility.rst
> > index 6bfa101ed71..236e5c72d81 100644
> > --- a/gcc/jit/docs/topics/compatibility.rst
> > +++ b/gcc/jit/docs/topics/compatibility.rst
> > @@ -226,3 +226,44 @@ entrypoints:
> >  --------------------
> >  ``LIBGCCJIT_ABI_14`` covers the addition of
> >  :func:`gcc_jit_global_set_initializer`
> > +
> > +.. _LIBGCCJIT_ABI_15:
> > +
> > +``LIBGCCJIT_ABI_15``
> > +--------------------
> > +``LIBGCCJIT_ABI_15`` covers the addition of reflection functions via
> > API
> > +entrypoints:
> 
> This needs updating, as I used LIBGCCJIT_ABI_15 for inline asm.
> 
> [...snip...]
> 
> > diff --git a/gcc/jit/docs/topics/functions.rst
> > b/gcc/jit/docs/topics/functions.rst
> > index eb40d64010e..aa6de87282d 100644
> > --- a/gcc/jit/docs/topics/functions.rst
> > +++ b/gcc/jit/docs/topics/functions.rst
> > @@ -171,6 +171,16 @@ Functions
> >     underlying string, so it is valid to pass in a pointer to an on-
> > stack
> >     buffer.
> >  
> > +.. function::  ssize_t \
> > +               gcc_jit_function_get_param_count (gcc_jit_function
> > *func)
> > +
> > +   Get the number of parameters of the function.
> > +
> > +.. function::  gcc_jit_type \*
> > +               gcc_jit_function_get_return_type (gcc_jit_function
> > *func)
> > +
> > +   Get the return type of the function.
> 
> As noted before, this doesn't yet document all the new entrypoints; I
> think you wanted to hold off until all the details were thrashed out,
> but hopefully we're close.
> 
> The documentation for an entrypoint should specify which ABI it was
> added in.
> 
> [...snip...]
> 
> > +/* Public entrypoint.  See description in libgccjit.h.
> > +
> > +   After error-checking, the real work is done by the
> > +   gcc::jit::recording::type::is_struct method, in
> > +   jit-recording.c.  */
> > +
> > +gcc_jit_struct *
> > +gcc_jit_type_is_struct (gcc_jit_type *type)
> > +{
> > +  RETURN_NULL_IF_FAIL (type, NULL, NULL, "NULL type");
> > +  gcc::jit::recording::struct_ *struct_type = type->is_struct ();
> > +  return (gcc_jit_struct *)struct_type;
> > +}
> > +
> > +/* Public entrypoint.  See description in libgccjit.h.
> > +
> > +   After error-checking, the real work is done by the
> > +   gcc::jit::recording::vector_type::get_num_units method, in
> > +   jit-recording.c.  */
> > +
> > +ssize_t
> > +gcc_jit_vector_type_get_num_units (gcc_jit_vector_type *vector_type)
> > +{
> > +  RETURN_VAL_IF_FAIL (vector_type, -1, NULL, NULL, "NULL
> > vector_type");
> > +  return vector_type->get_num_units ();
> > +}
> > +
> > +/* Public entrypoint.  See description in libgccjit.h.
> > +
> > +   After error-checking, the real work is done by the
> > +   gcc::jit::recording::vector_type::get_element_type method, in
> > +   jit-recording.c.  */
> > +
> > +gcc_jit_type *
> > +gcc_jit_vector_type_get_element_type (gcc_jit_vector_type
> > *vector_type)
> > +{
> > +  RETURN_NULL_IF_FAIL (vector_type, NULL, NULL, "NULL vector_type");
> > +  return (gcc_jit_type *)vector_type->get_element_type ();
> > +}
> > +
> > +/* Public entrypoint.  See description in libgccjit.h.
> > +
> > +   After error-checking, the real work is done by the
> > +   gcc::jit::recording::type::unqualified method, in
> > +   jit-recording.c.  */
> > +
> > +gcc_jit_type *
> > +gcc_jit_type_unqualified (gcc_jit_type *type)
> > +{
> > +  RETURN_NULL_IF_FAIL (type, NULL, NULL, "NULL type");
> > +
> > +  return (gcc_jit_type *)type->unqualified ();
> > +}
> > +
> > +/* Public entrypoint.  See description in libgccjit.h.
> > +
> > +   After error-checking, the real work is done by the
> > +   gcc::jit::recording::type::dyn_cast_function_type method, in
> > +   jit-recording.c.  */
> > +
> > +gcc_jit_function_type *
> > +gcc_jit_type_is_function_ptr_type (gcc_jit_type *type)
> > +{
> > +  RETURN_NULL_IF_FAIL (type, NULL, NULL, "NULL type");
> > +  gcc::jit::recording::type *func_ptr_type = type->dereference ();
> > +  RETURN_NULL_IF_FAIL (func_ptr_type, NULL, NULL, "NULL type");
> > +  gcc::jit::recording::function_type *func_type =
> > +    func_ptr_type->dyn_cast_function_type ();
> > +  RETURN_NULL_IF_FAIL (func_type, NULL, NULL, "NULL type");
> 
> I notice that the other new "*_is_*" functions don't fail if the
> dyncast returns NULL, whereas this one does.
> 
> RETURN_NULL_IF_FAIL calls jit_error; do we really want that?  It seems
> more consistent to have it return NULL without an error for the case
> where "type" isn't a function ptr type.
> 
> > +
> > +  return (gcc_jit_function_type *)func_type;
> > +}
> > +
> > +/* Public entrypoint.  See description in libgccjit.h.
> > +
> > +   After error-checking, the real work is done by the
> > +   gcc::jit::recording::function_type::get_return_type method, in
> > +   jit-recording.c.  */
> > +
> > +gcc_jit_type *
> > +gcc_jit_function_type_get_return_type (gcc_jit_function_type
> > *function_type)
> > +{
> > +  RETURN_NULL_IF_FAIL (function_type, NULL, NULL, "NULL
> > struct_type");
> 
> Wrong error message; should be "NULL function_type".
> 
> 
> > +  return (gcc_jit_type *)function_type->get_return_type ();
> > +}
> > +
> > +/* Public entrypoint.  See description in libgccjit.h.
> > +
> > +   After error-checking, the real work is done by the
> > +   gcc::jit::recording::function_type::get_param_types method, in
> > +   jit-recording.c.  */
> > +
> > +ssize_t
> > +gcc_jit_function_type_get_param_count (gcc_jit_function_type
> > *function_type)
> > +{
> > +  RETURN_VAL_IF_FAIL (function_type, -1, NULL, NULL, "NULL
> > struct_type");
> 
> Wrong error message; should be "NULL function_type".
> 
> > +  return function_type->get_param_types ().length ();
> > +}
> > +
> > +/* Public entrypoint.  See description in libgccjit.h.
> > +
> > +   After error-checking, the real work is done by the
> > +   gcc::jit::recording::function_type::get_param_types method, in
> > +   jit-recording.c.  */
> > +
> > +gcc_jit_type *
> > +gcc_jit_function_type_get_param_type (gcc_jit_function_type
> > *function_type,
> > +                               int index)
> > +{
> > +  RETURN_NULL_IF_FAIL (function_type, NULL, NULL, "NULL
> > struct_type");
> 
> Wrong error message; should be "NULL function_type".
> 
> 
> > +  int num_params = function_type->get_param_types ().length ();
> > +  gcc::jit::recording::context *ctxt = function_type->m_ctxt;
> 
> "index" should either be unsigned, or we need to check here for >= 0.
> 
> > +  RETURN_NULL_IF_FAIL_PRINTF3 (index < num_params,
> > +                              ctxt, NULL,
> > +                              "index of %d is too large (%s has %d
> > params)",
> > +                              index,
> > +                              function_type->get_debug_string (),
> > +                              num_params);
> > +  return (gcc_jit_type *)function_type->get_param_types ()[index];
> > +}
> > +
> >  /* Public entrypoint.  See description in libgccjit.h.
> >  
> >     After error-checking, the real work is done by the
> > @@ -731,6 +930,36 @@ gcc_jit_struct_set_fields (gcc_jit_struct
> > *struct_type,
> >                            (gcc::jit::recording::field **)fields);
> >  }
> >  
> > +
> > +/* Public entrypoint.  See description in libgccjit.h.
> > +
> > +   After error-checking, the real work is done by the
> > +   gcc::jit::recording::fields::get_field method in
> > +   jit-recording.c.  */
> > +extern gcc_jit_field *
> > +gcc_jit_struct_get_field (gcc_jit_struct *struct_type,
> > +                          int index)
> > +{
> > +  RETURN_NULL_IF_FAIL (struct_type, NULL, NULL, "NULL struct type");
> > +  RETURN_NULL_IF_FAIL (struct_type->get_fields (), NULL, NULL, "NULL
> > struct fields");
> 
> "index" should either be unsigned, or we need to check here for >= 0.
> 
> > +  RETURN_NULL_IF_FAIL (index < struct_type->get_fields ()->length
> > (), NULL,
> > +                               NULL, "NULL struct type");
> > +  return (gcc_jit_field *)struct_type->get_fields ()->get_field
> > (index);
> > +}
> 
> [...snip...]
> 
> > diff --git a/gcc/jit/libgccjit.h b/gcc/jit/libgccjit.h
> > index 7134841bb07..db4ccffb41c 100644
> > --- a/gcc/jit/libgccjit.h
> > +++ b/gcc/jit/libgccjit.h
> > @@ -96,6 +96,12 @@ typedef struct gcc_jit_field gcc_jit_field;
> >     the layout for, or an opaque type.  */
> >  typedef struct gcc_jit_struct gcc_jit_struct;
> >  
> > +/* A gcc_jit_function_type encapsulates a function type.  */
> > +typedef struct gcc_jit_function_type gcc_jit_function_type;
> > +
> > +/* A gcc_jit_vector_type encapsulates a vector type.  */
> > +typedef struct gcc_jit_vector_type gcc_jit_vector_type;
> > +
> 
> Please add these to the ASCII art inheritance diagram immediately
> above:
>   typedef struct gcc_jit_object gcc_jit_object;
> 
> [...snip...]
> 
> >  /* Unions work similarly to structs.  */
> >  extern gcc_jit_type *
> >  gcc_jit_context_new_union_type (gcc_jit_context *ctxt,
> > @@ -1518,6 +1533,78 @@ gcc_jit_version_minor (void);
> >  extern int
> >  gcc_jit_version_patchlevel (void);
> >  
> > +#define LIBGCCJIT_HAVE_REFLECTION
> > +
> > +/* Reflection functions to get the number of parameters, return type
> > of
> > +   a function and whether a type is a bool from the C API.
> > +
> > +   This API entrypoint was added in LIBGCCJIT_ABI_15; you can test
> > for its
> > +   presence using
> > +     #ifdef LIBGCCJIT_HAVE_REFLECTION
> > +*/
> > +/* Get the return type of a function.  */
> > +extern gcc_jit_type *
> > +gcc_jit_function_get_return_type (gcc_jit_function *func);
> > +
> > +/* Get the number of params of a function.  */
> > +extern ssize_t
> > +gcc_jit_function_get_param_count (gcc_jit_function *func);
> 
> You're using ssize_t here, why?  Wouldn't size_t be better?
> The count can't be negative.
> 
> Should we use size_t for indexes, rather than "int"?
> 
> (this happens in various places e.g.
> gcc_jit_function_type_get_param_count and
> gcc_jit_vector_type_get_num_units)
> 
> [...snip...]
> 
> > diff --git a/gcc/jit/libgccjit.map b/gcc/jit/libgccjit.map
> > index a6e67e781a4..720b6ca286f 100644
> > --- a/gcc/jit/libgccjit.map
> > +++ b/gcc/jit/libgccjit.map
> > @@ -192,3 +192,24 @@ LIBGCCJIT_ABI_14 {
> >    global:
> >      gcc_jit_global_set_initializer;
> >  } LIBGCCJIT_ABI_13;
> > +
> > +LIBGCCJIT_ABI_15 {
> > +  global:
> > +    gcc_jit_function_get_return_type;
> > +    gcc_jit_function_get_param_count;
> > +    gcc_jit_function_type_get_return_type;
> > +    gcc_jit_function_type_get_param_count;
> > +    gcc_jit_function_type_get_param_type;
> > +    gcc_jit_type_unqualified;
> > +    gcc_jit_type_is_array;
> > +    gcc_jit_type_is_bool;
> > +    gcc_jit_type_is_function_ptr_type;
> > +    gcc_jit_type_is_integral;
> > +    gcc_jit_type_is_pointer;
> > +    gcc_jit_type_is_vector;
> > +    gcc_jit_vector_type_get_element_type;
> > +    gcc_jit_vector_type_get_num_units;
> > +    gcc_jit_struct_get_field;
> > +    gcc_jit_type_is_struct;
> > +    gcc_jit_struct_get_field_count;
> > +} LIBGCCJIT_ABI_14;
> 
> As noted above, this will need to be LIBGCCJIT_ABI_16 as I used
> LIBGCCJIT_ABI_15 for inline asm.
> 
> [...snip...]
> 
> > diff --git a/gcc/testsuite/jit.dg/test-reflection.c
> > b/gcc/testsuite/jit.dg/test-reflection.c
> > new file mode 100644
> > index 00000000000..b3cf2942f3a
> > --- /dev/null
> > +++ b/gcc/testsuite/jit.dg/test-reflection.c
> > @@ -0,0 +1,89 @@
> > +#include <stdlib.h>
> > +#include <stdio.h>
> > +
> > +#include "libgccjit.h"
> > +
> > +#include "harness.h"
> > +
> > +void
> > +create_code (gcc_jit_context *ctxt, void *user_data)
> > +{
> > +  /* Do nothing.  */
> > +}
> > +
> > +void
> > +verify_code (gcc_jit_context *ctxt, gcc_jit_result *result)
> > +{
> > +  /* Get the built-in functions.  */
> > +  gcc_jit_function *builtin_sin =
> > +    gcc_jit_context_get_builtin_function (ctxt, "sin");
> > +
> > +  CHECK_VALUE (gcc_jit_function_get_param_count(builtin_sin), 1);
> > +
> > +  gcc_jit_type *double_type =
> > +    gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_DOUBLE);
> > +  CHECK_VALUE (gcc_jit_function_get_return_type(builtin_sin),
> > double_type);
> > +  CHECK (!gcc_jit_type_is_integral(double_type));
> > +
> > +  gcc_jit_type *bool_type =
> > +    gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_BOOL);
> > +  CHECK (gcc_jit_type_is_bool(bool_type));
> > +  CHECK (!gcc_jit_type_is_integral(bool_type));
> > +
> > +  gcc_jit_type *aligned_bool_type =
> > +    gcc_jit_type_get_aligned(gcc_jit_context_get_type (ctxt,
> > GCC_JIT_TYPE_BOOL), 8);
> > +  CHECK (gcc_jit_type_is_bool(aligned_bool_type));
> > +  CHECK (bool_type != aligned_bool_type);
> > +  CHECK_VALUE (gcc_jit_type_unqualified(aligned_bool_type),
> > bool_type);
> > +
> > +  CHECK_VALUE
> > (gcc_jit_type_unqualified(gcc_jit_type_get_const(bool_type)),
> > bool_type);
> > +  CHECK_VALUE
> > (gcc_jit_type_unqualified(gcc_jit_type_get_volatile(bool_type)),
> > bool_type);
> > +
> > +  gcc_jit_type *int64 =
> > +    gcc_jit_context_get_int_type(ctxt, 8, 1);
> > +  CHECK (gcc_jit_type_is_integral(int64));
> > +  gcc_jit_type *uint64 =
> > +    gcc_jit_context_get_int_type(ctxt, 8, 0);
> > +  CHECK (gcc_jit_type_is_integral(uint64));
> > +  gcc_jit_type *int8 =
> > +    gcc_jit_context_get_int_type(ctxt, 1, 1);
> > +  CHECK (gcc_jit_type_is_integral(int8));
> > +  gcc_jit_type *uint8 =
> > +    gcc_jit_context_get_int_type(ctxt, 1, 0);
> > +  CHECK (gcc_jit_type_is_integral(uint8));
> > +
> > +  CHECK (!gcc_jit_type_is_vector(double_type));
> > +  gcc_jit_type *vec_type = gcc_jit_type_get_vector (double_type, 4);
> > +  gcc_jit_vector_type *vector_type =
> > gcc_jit_type_is_vector(vec_type);
> > +  CHECK (vector_type);
> > +  CHECK (vec_type != double_type);
> > +  CHECK_VALUE (gcc_jit_vector_type_get_element_type(vector_type),
> > double_type);
> > +  CHECK_VALUE (gcc_jit_vector_type_get_num_units(vector_type), 4);
> > +
> > +  CHECK (!gcc_jit_type_is_pointer(double_type));
> > +  CHECK_VALUE
> > (gcc_jit_type_is_pointer(gcc_jit_type_get_pointer(double_type)),
> > double_type);
> > +
> > +  gcc_jit_type* params[2] = {int8, uint64};
> > +  gcc_jit_type *function_ptr_type =
> > gcc_jit_context_new_function_ptr_type(ctxt, NULL, int64, 2, params,
> > 0);
> > +  gcc_jit_function_type *function_type =
> > gcc_jit_type_is_function_ptr_type (function_ptr_type);
> > +  CHECK (function_type);
> > +  int param_count =
> > gcc_jit_function_type_get_param_count(function_type);
> > +  CHECK_VALUE (param_count, 2);
> > +  gcc_jit_type *return_type =
> > gcc_jit_function_type_get_return_type(function_type);
> > +  CHECK_VALUE (return_type, int64);
> > +  gcc_jit_type *param1 =
> > gcc_jit_function_type_get_param_type(function_type, 0);
> > +  CHECK_VALUE (param1, int8);
> > +  gcc_jit_type *param2 =
> > gcc_jit_function_type_get_param_type(function_type, 1);
> > +  CHECK_VALUE (param2, uint64);
> > +
> > +  gcc_jit_field *field1 = gcc_jit_context_new_field (ctxt, NULL,
> > uint64, "field1");
> > +  gcc_jit_field *field2 = gcc_jit_context_new_field (ctxt, NULL,
> > double_type, "field2");
> > +  gcc_jit_field *fields[2] = { field1, field2 };
> > +  gcc_jit_struct *struct_type = gcc_jit_context_new_struct_type
> > (ctxt, NULL, "testStruct", 2, fields);
> > +  CHECK_VALUE (gcc_jit_struct_get_field_count(struct_type), 2);
> > +  CHECK_VALUE (gcc_jit_struct_get_field(struct_type, 0), field1);
> > +  CHECK_VALUE (gcc_jit_struct_get_field(struct_type, 1), field2);
> > +  gcc_jit_struct *struct_ty =
> > gcc_jit_type_is_struct(gcc_jit_struct_as_type(struct_type));
> > +  CHECK_VALUE (struct_ty, struct_type);
> 
> 
> I think this is missing test coverage for the various gcc_jit_type_is_*
> entrypoints gracefully returning NULL when the type passed to them is
> wrong (e.g. a non-struct type passed to gcc_jit_type_is_struct, etc)
> 
> Hope this is constructive; sorry again about the delay in reviewing it.
> Dave
> 
> 



^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re: [PATCH] libgccjit: add some reflection functions in the jit C api
  2021-05-26  0:19                 ` Antoni Boucher
@ 2021-05-27 22:19                   ` David Malcolm
  2021-05-28  1:51                     ` Antoni Boucher
  0 siblings, 1 reply; 35+ messages in thread
From: David Malcolm @ 2021-05-27 22:19 UTC (permalink / raw)
  To: Antoni Boucher; +Cc: Andrea Corallo, Antoni Boucher via Jit, gcc-patches

On Tue, 2021-05-25 at 20:19 -0400, Antoni Boucher wrote:
> @David: PING
> 
> As far as I know, the only remaining question is about using
> `ssize_t`
> for the return type of some functions.
> Here's why I use this type:
> 
> That seemed off to return NULL for the functions returning a 
> size_t to indicate an error. So I changed it to return -1 (and return
> type to ssize_t). Is that the proper way to indicate an error?
> 
> Once I know the answer for this error handling question, I'll fix the
> types.
> 
> Thanks!

I think the things that accept params for indexes should be size_t
(i.e. unsigned).

As for the error-handling, I've been going back and forth.

The various return of -1 in the patch all occur when NULL is passed in
as the gcc_jit_foo*, for the various foo. Unfortunately this means that
we can't get at a jit context to emit the error on, so jit_error is
called with a NULL context, and hence merely prints to stderr; it can't
set state on any jit context.

Presumably if the code is passing in NULL for one of these things, then
something's gone wrong already.

Option (A): returning a size_t (unsigned):
- No way to indicate error if the user passes in NULL, or a bogus
value, beyond output on stderr; we have to defensively return 0, which
the user's code is likely to gracefully handle

Option (B): returning a ssize_t:
- Can return -1 if the user passes in NULL or a bogus value.  But if
the user doesn't check for -1 and blithely casts to unsigned (e.g.
allocating a buffer), their code is likely to explode with a very large
allocation.

Consider e.g. gcc_jit_function_type_get_param_count.  If the user uses 
gcc_jit_type_is_function_ptr_type to dynamically cast some type to
function_type and forgets to check, and passes in NULL, then...

...with option (A), it returns 0, as if the function has no params;
eventually a type-checking error occurs.

...with option (B), it returns -1, and the user who didn't check before
has to check again

So I think I prefer option (A), but I'm willing to be convinced on the
alternative.

I also now think that the dynamic cast functions (e.g.
gcc_jit_type_is_function_ptr_type) should be "_dyncast_" rather than
"_is_" (e.g. gcc_jit_type_dyncast_function_ptr_type) to make it clear
that this is a dynamic cast that can fail, and to contrast them with
the "_as_" functions which are static casts.

Hope this makes sense and is constructive.
Dave


> 
> Le jeudi 13 mai 2021 à 17:30 -0400, David Malcolm a écrit :
> > On Tue, 2020-11-03 at 17:13 -0500, Antoni Boucher wrote:
> > > I was missing a check in gcc_jit_struct_get_field, I added it in
> > > this
> > > new patch.
> > > 
> > 
> > Sorry about the long delay in reviewing this patch.
> > 
> > The main high-level points are:
> > - currently the get_*_count functions return "ssize_t" - why?  Only
> > unsigned values are meaningful; shouldn't they return "size_t"
> > instead?
> > 
> > - the various "lookup by index" functions take "int" i.e. signed, but
> > only >= 0 is meaningful.  I think it makes sense to make them take
> > size_t instead.
> > 
> > Sorry if we covered that before in the review, it's been a while.
> > 
> > Various nitpicks inline below...
> > 
> > [...snip...]
> >  
> > > diff --git a/gcc/jit/docs/topics/compatibility.rst
> > > b/gcc/jit/docs/topics/compatibility.rst
> > > index 6bfa101ed71..236e5c72d81 100644
> > > --- a/gcc/jit/docs/topics/compatibility.rst
> > > +++ b/gcc/jit/docs/topics/compatibility.rst
> > > @@ -226,3 +226,44 @@ entrypoints:
> > >  --------------------
> > >  ``LIBGCCJIT_ABI_14`` covers the addition of
> > >  :func:`gcc_jit_global_set_initializer`
> > > +
> > > +.. _LIBGCCJIT_ABI_15:
> > > +
> > > +``LIBGCCJIT_ABI_15``
> > > +--------------------
> > > +``LIBGCCJIT_ABI_15`` covers the addition of reflection functions
> > > via
> > > API
> > > +entrypoints:
> > 
> > This needs updating, as I used LIBGCCJIT_ABI_15 for inline asm.
> > 
> > [...snip...]
> > 
> > > diff --git a/gcc/jit/docs/topics/functions.rst
> > > b/gcc/jit/docs/topics/functions.rst
> > > index eb40d64010e..aa6de87282d 100644
> > > --- a/gcc/jit/docs/topics/functions.rst
> > > +++ b/gcc/jit/docs/topics/functions.rst
> > > @@ -171,6 +171,16 @@ Functions
> > >     underlying string, so it is valid to pass in a pointer to an
> > > on-
> > > stack
> > >     buffer.
> > >  
> > > +.. function::  ssize_t \
> > > +               gcc_jit_function_get_param_count (gcc_jit_function
> > > *func)
> > > +
> > > +   Get the number of parameters of the function.
> > > +
> > > +.. function::  gcc_jit_type \*
> > > +               gcc_jit_function_get_return_type (gcc_jit_function
> > > *func)
> > > +
> > > +   Get the return type of the function.
> > 
> > As noted before, this doesn't yet document all the new entrypoints; I
> > think you wanted to hold off until all the details were thrashed out,
> > but hopefully we're close.
> > 
> > The documentation for an entrypoint should specify which ABI it was
> > added in.
> > 
> > [...snip...]
> > 
> > > +/* Public entrypoint.  See description in libgccjit.h.
> > > +
> > > +   After error-checking, the real work is done by the
> > > +   gcc::jit::recording::type::is_struct method, in
> > > +   jit-recording.c.  */
> > > +
> > > +gcc_jit_struct *
> > > +gcc_jit_type_is_struct (gcc_jit_type *type)
> > > +{
> > > +  RETURN_NULL_IF_FAIL (type, NULL, NULL, "NULL type");
> > > +  gcc::jit::recording::struct_ *struct_type = type->is_struct ();
> > > +  return (gcc_jit_struct *)struct_type;
> > > +}
> > > +
> > > +/* Public entrypoint.  See description in libgccjit.h.
> > > +
> > > +   After error-checking, the real work is done by the
> > > +   gcc::jit::recording::vector_type::get_num_units method, in
> > > +   jit-recording.c.  */
> > > +
> > > +ssize_t
> > > +gcc_jit_vector_type_get_num_units (gcc_jit_vector_type
> > > *vector_type)
> > > +{
> > > +  RETURN_VAL_IF_FAIL (vector_type, -1, NULL, NULL, "NULL
> > > vector_type");
> > > +  return vector_type->get_num_units ();
> > > +}
> > > +
> > > +/* Public entrypoint.  See description in libgccjit.h.
> > > +
> > > +   After error-checking, the real work is done by the
> > > +   gcc::jit::recording::vector_type::get_element_type method, in
> > > +   jit-recording.c.  */
> > > +
> > > +gcc_jit_type *
> > > +gcc_jit_vector_type_get_element_type (gcc_jit_vector_type
> > > *vector_type)
> > > +{
> > > +  RETURN_NULL_IF_FAIL (vector_type, NULL, NULL, "NULL
> > > vector_type");
> > > +  return (gcc_jit_type *)vector_type->get_element_type ();
> > > +}
> > > +
> > > +/* Public entrypoint.  See description in libgccjit.h.
> > > +
> > > +   After error-checking, the real work is done by the
> > > +   gcc::jit::recording::type::unqualified method, in
> > > +   jit-recording.c.  */
> > > +
> > > +gcc_jit_type *
> > > +gcc_jit_type_unqualified (gcc_jit_type *type)
> > > +{
> > > +  RETURN_NULL_IF_FAIL (type, NULL, NULL, "NULL type");
> > > +
> > > +  return (gcc_jit_type *)type->unqualified ();
> > > +}
> > > +
> > > +/* Public entrypoint.  See description in libgccjit.h.
> > > +
> > > +   After error-checking, the real work is done by the
> > > +   gcc::jit::recording::type::dyn_cast_function_type method, in
> > > +   jit-recording.c.  */
> > > +
> > > +gcc_jit_function_type *
> > > +gcc_jit_type_is_function_ptr_type (gcc_jit_type *type)
> > > +{
> > > +  RETURN_NULL_IF_FAIL (type, NULL, NULL, "NULL type");
> > > +  gcc::jit::recording::type *func_ptr_type = type->dereference ();
> > > +  RETURN_NULL_IF_FAIL (func_ptr_type, NULL, NULL, "NULL type");
> > > +  gcc::jit::recording::function_type *func_type =
> > > +    func_ptr_type->dyn_cast_function_type ();
> > > +  RETURN_NULL_IF_FAIL (func_type, NULL, NULL, "NULL type");
> > 
> > I notice that the other new "*_is_*" functions don't fail if the
> > dyncast returns NULL, whereas this one does.
> > 
> > RETURN_NULL_IF_FAIL calls jit_error; do we really want that?  It
> > seems
> > more consistent to have it return NULL without an error for the case
> > where "type" isn't a function ptr type.
> > 
> > > +
> > > +  return (gcc_jit_function_type *)func_type;
> > > +}
> > > +
> > > +/* Public entrypoint.  See description in libgccjit.h.
> > > +
> > > +   After error-checking, the real work is done by the
> > > +   gcc::jit::recording::function_type::get_return_type method, in
> > > +   jit-recording.c.  */
> > > +
> > > +gcc_jit_type *
> > > +gcc_jit_function_type_get_return_type (gcc_jit_function_type
> > > *function_type)
> > > +{
> > > +  RETURN_NULL_IF_FAIL (function_type, NULL, NULL, "NULL
> > > struct_type");
> > 
> > Wrong error message; should be "NULL function_type".
> > 
> > 
> > > +  return (gcc_jit_type *)function_type->get_return_type ();
> > > +}
> > > +
> > > +/* Public entrypoint.  See description in libgccjit.h.
> > > +
> > > +   After error-checking, the real work is done by the
> > > +   gcc::jit::recording::function_type::get_param_types method, in
> > > +   jit-recording.c.  */
> > > +
> > > +ssize_t
> > > +gcc_jit_function_type_get_param_count (gcc_jit_function_type
> > > *function_type)
> > > +{
> > > +  RETURN_VAL_IF_FAIL (function_type, -1, NULL, NULL, "NULL
> > > struct_type");
> > 
> > Wrong error message; should be "NULL function_type".
> > 
> > > +  return function_type->get_param_types ().length ();
> > > +}
> > > +
> > > +/* Public entrypoint.  See description in libgccjit.h.
> > > +
> > > +   After error-checking, the real work is done by the
> > > +   gcc::jit::recording::function_type::get_param_types method, in
> > > +   jit-recording.c.  */
> > > +
> > > +gcc_jit_type *
> > > +gcc_jit_function_type_get_param_type (gcc_jit_function_type
> > > *function_type,
> > > +                               int index)
> > > +{
> > > +  RETURN_NULL_IF_FAIL (function_type, NULL, NULL, "NULL
> > > struct_type");
> > 
> > Wrong error message; should be "NULL function_type".
> > 
> > 
> > > +  int num_params = function_type->get_param_types ().length ();
> > > +  gcc::jit::recording::context *ctxt = function_type->m_ctxt;
> > 
> > "index" should either be unsigned, or we need to check here for >= 0.
> > 
> > > +  RETURN_NULL_IF_FAIL_PRINTF3 (index < num_params,
> > > +                              ctxt, NULL,
> > > +                              "index of %d is too large (%s has %d
> > > params)",
> > > +                              index,
> > > +                              function_type->get_debug_string (),
> > > +                              num_params);
> > > +  return (gcc_jit_type *)function_type->get_param_types ()[index];
> > > +}
> > > +
> > >  /* Public entrypoint.  See description in libgccjit.h.
> > >  
> > >     After error-checking, the real work is done by the
> > > @@ -731,6 +930,36 @@ gcc_jit_struct_set_fields (gcc_jit_struct
> > > *struct_type,
> > >                            (gcc::jit::recording::field **)fields);
> > >  }
> > >  
> > > +
> > > +/* Public entrypoint.  See description in libgccjit.h.
> > > +
> > > +   After error-checking, the real work is done by the
> > > +   gcc::jit::recording::fields::get_field method in
> > > +   jit-recording.c.  */
> > > +extern gcc_jit_field *
> > > +gcc_jit_struct_get_field (gcc_jit_struct *struct_type,
> > > +                          int index)
> > > +{
> > > +  RETURN_NULL_IF_FAIL (struct_type, NULL, NULL, "NULL struct
> > > type");
> > > +  RETURN_NULL_IF_FAIL (struct_type->get_fields (), NULL, NULL,
> > > "NULL
> > > struct fields");
> > 
> > "index" should either be unsigned, or we need to check here for >= 0.
> > 
> > > +  RETURN_NULL_IF_FAIL (index < struct_type->get_fields ()->length
> > > (), NULL,
> > > +                               NULL, "NULL struct type");
> > > +  return (gcc_jit_field *)struct_type->get_fields ()->get_field
> > > (index);
> > > +}
> > 
> > [...snip...]
> > 
> > > diff --git a/gcc/jit/libgccjit.h b/gcc/jit/libgccjit.h
> > > index 7134841bb07..db4ccffb41c 100644
> > > --- a/gcc/jit/libgccjit.h
> > > +++ b/gcc/jit/libgccjit.h
> > > @@ -96,6 +96,12 @@ typedef struct gcc_jit_field gcc_jit_field;
> > >     the layout for, or an opaque type.  */
> > >  typedef struct gcc_jit_struct gcc_jit_struct;
> > >  
> > > +/* A gcc_jit_function_type encapsulates a function type.  */
> > > +typedef struct gcc_jit_function_type gcc_jit_function_type;
> > > +
> > > +/* A gcc_jit_vector_type encapsulates a vector type.  */
> > > +typedef struct gcc_jit_vector_type gcc_jit_vector_type;
> > > +
> > 
> > Please add these to the ASCII art inheritance diagram immediately
> > above:
> >   typedef struct gcc_jit_object gcc_jit_object;
> > 
> > [...snip...]
> > 
> > >  /* Unions work similarly to structs.  */
> > >  extern gcc_jit_type *
> > >  gcc_jit_context_new_union_type (gcc_jit_context *ctxt,
> > > @@ -1518,6 +1533,78 @@ gcc_jit_version_minor (void);
> > >  extern int
> > >  gcc_jit_version_patchlevel (void);
> > >  
> > > +#define LIBGCCJIT_HAVE_REFLECTION
> > > +
> > > +/* Reflection functions to get the number of parameters, return
> > > type
> > > of
> > > +   a function and whether a type is a bool from the C API.
> > > +
> > > +   This API entrypoint was added in LIBGCCJIT_ABI_15; you can test
> > > for its
> > > +   presence using
> > > +     #ifdef LIBGCCJIT_HAVE_REFLECTION
> > > +*/
> > > +/* Get the return type of a function.  */
> > > +extern gcc_jit_type *
> > > +gcc_jit_function_get_return_type (gcc_jit_function *func);
> > > +
> > > +/* Get the number of params of a function.  */
> > > +extern ssize_t
> > > +gcc_jit_function_get_param_count (gcc_jit_function *func);
> > 
> > You're using ssize_t here, why?  Wouldn't size_t be better?
> > The count can't be negative.
> > 
> > Should we use size_t for indexes, rather than "int"?
> > 
> > (this happens in various places e.g.
> > gcc_jit_function_type_get_param_count and
> > gcc_jit_vector_type_get_num_units)
> > 
> > [...snip...]
> > 
> > > diff --git a/gcc/jit/libgccjit.map b/gcc/jit/libgccjit.map
> > > index a6e67e781a4..720b6ca286f 100644
> > > --- a/gcc/jit/libgccjit.map
> > > +++ b/gcc/jit/libgccjit.map
> > > @@ -192,3 +192,24 @@ LIBGCCJIT_ABI_14 {
> > >    global:
> > >      gcc_jit_global_set_initializer;
> > >  } LIBGCCJIT_ABI_13;
> > > +
> > > +LIBGCCJIT_ABI_15 {
> > > +  global:
> > > +    gcc_jit_function_get_return_type;
> > > +    gcc_jit_function_get_param_count;
> > > +    gcc_jit_function_type_get_return_type;
> > > +    gcc_jit_function_type_get_param_count;
> > > +    gcc_jit_function_type_get_param_type;
> > > +    gcc_jit_type_unqualified;
> > > +    gcc_jit_type_is_array;
> > > +    gcc_jit_type_is_bool;
> > > +    gcc_jit_type_is_function_ptr_type;
> > > +    gcc_jit_type_is_integral;
> > > +    gcc_jit_type_is_pointer;
> > > +    gcc_jit_type_is_vector;
> > > +    gcc_jit_vector_type_get_element_type;
> > > +    gcc_jit_vector_type_get_num_units;
> > > +    gcc_jit_struct_get_field;
> > > +    gcc_jit_type_is_struct;
> > > +    gcc_jit_struct_get_field_count;
> > > +} LIBGCCJIT_ABI_14;
> > 
> > As noted above, this will need to be LIBGCCJIT_ABI_16 as I used
> > LIBGCCJIT_ABI_15 for inline asm.
> > 
> > [...snip...]
> > 
> > > diff --git a/gcc/testsuite/jit.dg/test-reflection.c
> > > b/gcc/testsuite/jit.dg/test-reflection.c
> > > new file mode 100644
> > > index 00000000000..b3cf2942f3a
> > > --- /dev/null
> > > +++ b/gcc/testsuite/jit.dg/test-reflection.c
> > > @@ -0,0 +1,89 @@
> > > +#include <stdlib.h>
> > > +#include <stdio.h>
> > > +
> > > +#include "libgccjit.h"
> > > +
> > > +#include "harness.h"
> > > +
> > > +void
> > > +create_code (gcc_jit_context *ctxt, void *user_data)
> > > +{
> > > +  /* Do nothing.  */
> > > +}
> > > +
> > > +void
> > > +verify_code (gcc_jit_context *ctxt, gcc_jit_result *result)
> > > +{
> > > +  /* Get the built-in functions.  */
> > > +  gcc_jit_function *builtin_sin =
> > > +    gcc_jit_context_get_builtin_function (ctxt, "sin");
> > > +
> > > +  CHECK_VALUE (gcc_jit_function_get_param_count(builtin_sin), 1);
> > > +
> > > +  gcc_jit_type *double_type =
> > > +    gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_DOUBLE);
> > > +  CHECK_VALUE (gcc_jit_function_get_return_type(builtin_sin),
> > > double_type);
> > > +  CHECK (!gcc_jit_type_is_integral(double_type));
> > > +
> > > +  gcc_jit_type *bool_type =
> > > +    gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_BOOL);
> > > +  CHECK (gcc_jit_type_is_bool(bool_type));
> > > +  CHECK (!gcc_jit_type_is_integral(bool_type));
> > > +
> > > +  gcc_jit_type *aligned_bool_type =
> > > +    gcc_jit_type_get_aligned(gcc_jit_context_get_type (ctxt,
> > > GCC_JIT_TYPE_BOOL), 8);
> > > +  CHECK (gcc_jit_type_is_bool(aligned_bool_type));
> > > +  CHECK (bool_type != aligned_bool_type);
> > > +  CHECK_VALUE (gcc_jit_type_unqualified(aligned_bool_type),
> > > bool_type);
> > > +
> > > +  CHECK_VALUE
> > > (gcc_jit_type_unqualified(gcc_jit_type_get_const(bool_type)),
> > > bool_type);
> > > +  CHECK_VALUE
> > > (gcc_jit_type_unqualified(gcc_jit_type_get_volatile(bool_type)),
> > > bool_type);
> > > +
> > > +  gcc_jit_type *int64 =
> > > +    gcc_jit_context_get_int_type(ctxt, 8, 1);
> > > +  CHECK (gcc_jit_type_is_integral(int64));
> > > +  gcc_jit_type *uint64 =
> > > +    gcc_jit_context_get_int_type(ctxt, 8, 0);
> > > +  CHECK (gcc_jit_type_is_integral(uint64));
> > > +  gcc_jit_type *int8 =
> > > +    gcc_jit_context_get_int_type(ctxt, 1, 1);
> > > +  CHECK (gcc_jit_type_is_integral(int8));
> > > +  gcc_jit_type *uint8 =
> > > +    gcc_jit_context_get_int_type(ctxt, 1, 0);
> > > +  CHECK (gcc_jit_type_is_integral(uint8));
> > > +
> > > +  CHECK (!gcc_jit_type_is_vector(double_type));
> > > +  gcc_jit_type *vec_type = gcc_jit_type_get_vector (double_type,
> > > 4);
> > > +  gcc_jit_vector_type *vector_type =
> > > gcc_jit_type_is_vector(vec_type);
> > > +  CHECK (vector_type);
> > > +  CHECK (vec_type != double_type);
> > > +  CHECK_VALUE (gcc_jit_vector_type_get_element_type(vector_type),
> > > double_type);
> > > +  CHECK_VALUE (gcc_jit_vector_type_get_num_units(vector_type), 4);
> > > +
> > > +  CHECK (!gcc_jit_type_is_pointer(double_type));
> > > +  CHECK_VALUE
> > > (gcc_jit_type_is_pointer(gcc_jit_type_get_pointer(double_type)),
> > > double_type);
> > > +
> > > +  gcc_jit_type* params[2] = {int8, uint64};
> > > +  gcc_jit_type *function_ptr_type =
> > > gcc_jit_context_new_function_ptr_type(ctxt, NULL, int64, 2, params,
> > > 0);
> > > +  gcc_jit_function_type *function_type =
> > > gcc_jit_type_is_function_ptr_type (function_ptr_type);
> > > +  CHECK (function_type);
> > > +  int param_count =
> > > gcc_jit_function_type_get_param_count(function_type);
> > > +  CHECK_VALUE (param_count, 2);
> > > +  gcc_jit_type *return_type =
> > > gcc_jit_function_type_get_return_type(function_type);
> > > +  CHECK_VALUE (return_type, int64);
> > > +  gcc_jit_type *param1 =
> > > gcc_jit_function_type_get_param_type(function_type, 0);
> > > +  CHECK_VALUE (param1, int8);
> > > +  gcc_jit_type *param2 =
> > > gcc_jit_function_type_get_param_type(function_type, 1);
> > > +  CHECK_VALUE (param2, uint64);
> > > +
> > > +  gcc_jit_field *field1 = gcc_jit_context_new_field (ctxt, NULL,
> > > uint64, "field1");
> > > +  gcc_jit_field *field2 = gcc_jit_context_new_field (ctxt, NULL,
> > > double_type, "field2");
> > > +  gcc_jit_field *fields[2] = { field1, field2 };
> > > +  gcc_jit_struct *struct_type = gcc_jit_context_new_struct_type
> > > (ctxt, NULL, "testStruct", 2, fields);
> > > +  CHECK_VALUE (gcc_jit_struct_get_field_count(struct_type), 2);
> > > +  CHECK_VALUE (gcc_jit_struct_get_field(struct_type, 0), field1);
> > > +  CHECK_VALUE (gcc_jit_struct_get_field(struct_type, 1), field2);
> > > +  gcc_jit_struct *struct_ty =
> > > gcc_jit_type_is_struct(gcc_jit_struct_as_type(struct_type));
> > > +  CHECK_VALUE (struct_ty, struct_type);
> > 
> > 
> > I think this is missing test coverage for the various
> > gcc_jit_type_is_*
> > entrypoints gracefully returning NULL when the type passed to them is
> > wrong (e.g. a non-struct type passed to gcc_jit_type_is_struct, etc)
> > 
> > Hope this is constructive; sorry again about the delay in reviewing
> > it.
> > Dave
> > 
> > 
> 
> 



^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re: [PATCH] libgccjit: add some reflection functions in the jit C api
  2021-05-27 22:19                   ` David Malcolm
@ 2021-05-28  1:51                     ` Antoni Boucher
  2021-06-10 22:41                       ` David Malcolm
  0 siblings, 1 reply; 35+ messages in thread
From: Antoni Boucher @ 2021-05-28  1:51 UTC (permalink / raw)
  To: David Malcolm; +Cc: Andrea Corallo, Antoni Boucher via Jit, gcc-patches

[-- Attachment #1: Type: text/plain, Size: 22990 bytes --]

I chose option A, so everything is a size_t, now.
I also renamed the dyncast functions.
Here's the new patch.

Le jeudi 27 mai 2021 à 18:19 -0400, David Malcolm a écrit :
> On Tue, 2021-05-25 at 20:19 -0400, Antoni Boucher wrote:
> > @David: PING
> > 
> > As far as I know, the only remaining question is about using
> > `ssize_t`
> > for the return type of some functions.
> > Here's why I use this type:
> > 
> > That seemed off to return NULL for the functions returning a 
> > size_t to indicate an error. So I changed it to return -1 (and
> > return
> > type to ssize_t). Is that the proper way to indicate an error?
> > 
> > Once I know the answer for this error handling question, I'll fix
> > the
> > types.
> > 
> > Thanks!
> 
> I think the things that accept params for indexes should be size_t
> (i.e. unsigned).
> 
> As for the error-handling, I've been going back and forth.
> 
> The various return of -1 in the patch all occur when NULL is passed
> in
> as the gcc_jit_foo*, for the various foo. Unfortunately this means
> that
> we can't get at a jit context to emit the error on, so jit_error is
> called with a NULL context, and hence merely prints to stderr; it
> can't
> set state on any jit context.
> 
> Presumably if the code is passing in NULL for one of these things,
> then
> something's gone wrong already.
> 
> Option (A): returning a size_t (unsigned):
> - No way to indicate error if the user passes in NULL, or a bogus
> value, beyond output on stderr; we have to defensively return 0,
> which
> the user's code is likely to gracefully handle
> 
> Option (B): returning a ssize_t:
> - Can return -1 if the user passes in NULL or a bogus value.  But if
> the user doesn't check for -1 and blithely casts to unsigned (e.g.
> allocating a buffer), their code is likely to explode with a very
> large
> allocation.
> 
> Consider e.g. gcc_jit_function_type_get_param_count.  If the user
> uses 
> gcc_jit_type_is_function_ptr_type to dynamically cast some type to
> function_type and forgets to check, and passes in NULL, then...
> 
> ...with option (A), it returns 0, as if the function has no params;
> eventually a type-checking error occurs.
> 
> ...with option (B), it returns -1, and the user who didn't check
> before
> has to check again
> 
> So I think I prefer option (A), but I'm willing to be convinced on
> the
> alternative.
> 
> I also now think that the dynamic cast functions (e.g.
> gcc_jit_type_is_function_ptr_type) should be "_dyncast_" rather than
> "_is_" (e.g. gcc_jit_type_dyncast_function_ptr_type) to make it clear
> that this is a dynamic cast that can fail, and to contrast them with
> the "_as_" functions which are static casts.
> 
> Hope this makes sense and is constructive.
> Dave
> 
> 
> > 
> > Le jeudi 13 mai 2021 à 17:30 -0400, David Malcolm a écrit :
> > > On Tue, 2020-11-03 at 17:13 -0500, Antoni Boucher wrote:
> > > > I was missing a check in gcc_jit_struct_get_field, I added it
> > > > in
> > > > this
> > > > new patch.
> > > > 
> > > 
> > > Sorry about the long delay in reviewing this patch.
> > > 
> > > The main high-level points are:
> > > - currently the get_*_count functions return "ssize_t" - why? 
> > > Only
> > > unsigned values are meaningful; shouldn't they return "size_t"
> > > instead?
> > > 
> > > - the various "lookup by index" functions take "int" i.e. signed,
> > > but
> > > only >= 0 is meaningful.  I think it makes sense to make them
> > > take
> > > size_t instead.
> > > 
> > > Sorry if we covered that before in the review, it's been a while.
> > > 
> > > Various nitpicks inline below...
> > > 
> > > [...snip...]
> > >  
> > > > diff --git a/gcc/jit/docs/topics/compatibility.rst
> > > > b/gcc/jit/docs/topics/compatibility.rst
> > > > index 6bfa101ed71..236e5c72d81 100644
> > > > --- a/gcc/jit/docs/topics/compatibility.rst
> > > > +++ b/gcc/jit/docs/topics/compatibility.rst
> > > > @@ -226,3 +226,44 @@ entrypoints:
> > > >  --------------------
> > > >  ``LIBGCCJIT_ABI_14`` covers the addition of
> > > >  :func:`gcc_jit_global_set_initializer`
> > > > +
> > > > +.. _LIBGCCJIT_ABI_15:
> > > > +
> > > > +``LIBGCCJIT_ABI_15``
> > > > +--------------------
> > > > +``LIBGCCJIT_ABI_15`` covers the addition of reflection
> > > > functions
> > > > via
> > > > API
> > > > +entrypoints:
> > > 
> > > This needs updating, as I used LIBGCCJIT_ABI_15 for inline asm.
> > > 
> > > [...snip...]
> > > 
> > > > diff --git a/gcc/jit/docs/topics/functions.rst
> > > > b/gcc/jit/docs/topics/functions.rst
> > > > index eb40d64010e..aa6de87282d 100644
> > > > --- a/gcc/jit/docs/topics/functions.rst
> > > > +++ b/gcc/jit/docs/topics/functions.rst
> > > > @@ -171,6 +171,16 @@ Functions
> > > >     underlying string, so it is valid to pass in a pointer to
> > > > an
> > > > on-
> > > > stack
> > > >     buffer.
> > > >  
> > > > +.. function::  ssize_t \
> > > > +               gcc_jit_function_get_param_count
> > > > (gcc_jit_function
> > > > *func)
> > > > +
> > > > +   Get the number of parameters of the function.
> > > > +
> > > > +.. function::  gcc_jit_type \*
> > > > +               gcc_jit_function_get_return_type
> > > > (gcc_jit_function
> > > > *func)
> > > > +
> > > > +   Get the return type of the function.
> > > 
> > > As noted before, this doesn't yet document all the new
> > > entrypoints; I
> > > think you wanted to hold off until all the details were thrashed
> > > out,
> > > but hopefully we're close.
> > > 
> > > The documentation for an entrypoint should specify which ABI it
> > > was
> > > added in.
> > > 
> > > [...snip...]
> > > 
> > > > +/* Public entrypoint.  See description in libgccjit.h.
> > > > +
> > > > +   After error-checking, the real work is done by the
> > > > +   gcc::jit::recording::type::is_struct method, in
> > > > +   jit-recording.c.  */
> > > > +
> > > > +gcc_jit_struct *
> > > > +gcc_jit_type_is_struct (gcc_jit_type *type)
> > > > +{
> > > > +  RETURN_NULL_IF_FAIL (type, NULL, NULL, "NULL type");
> > > > +  gcc::jit::recording::struct_ *struct_type = type->is_struct
> > > > ();
> > > > +  return (gcc_jit_struct *)struct_type;
> > > > +}
> > > > +
> > > > +/* Public entrypoint.  See description in libgccjit.h.
> > > > +
> > > > +   After error-checking, the real work is done by the
> > > > +   gcc::jit::recording::vector_type::get_num_units method, in
> > > > +   jit-recording.c.  */
> > > > +
> > > > +ssize_t
> > > > +gcc_jit_vector_type_get_num_units (gcc_jit_vector_type
> > > > *vector_type)
> > > > +{
> > > > +  RETURN_VAL_IF_FAIL (vector_type, -1, NULL, NULL, "NULL
> > > > vector_type");
> > > > +  return vector_type->get_num_units ();
> > > > +}
> > > > +
> > > > +/* Public entrypoint.  See description in libgccjit.h.
> > > > +
> > > > +   After error-checking, the real work is done by the
> > > > +   gcc::jit::recording::vector_type::get_element_type method,
> > > > in
> > > > +   jit-recording.c.  */
> > > > +
> > > > +gcc_jit_type *
> > > > +gcc_jit_vector_type_get_element_type (gcc_jit_vector_type
> > > > *vector_type)
> > > > +{
> > > > +  RETURN_NULL_IF_FAIL (vector_type, NULL, NULL, "NULL
> > > > vector_type");
> > > > +  return (gcc_jit_type *)vector_type->get_element_type ();
> > > > +}
> > > > +
> > > > +/* Public entrypoint.  See description in libgccjit.h.
> > > > +
> > > > +   After error-checking, the real work is done by the
> > > > +   gcc::jit::recording::type::unqualified method, in
> > > > +   jit-recording.c.  */
> > > > +
> > > > +gcc_jit_type *
> > > > +gcc_jit_type_unqualified (gcc_jit_type *type)
> > > > +{
> > > > +  RETURN_NULL_IF_FAIL (type, NULL, NULL, "NULL type");
> > > > +
> > > > +  return (gcc_jit_type *)type->unqualified ();
> > > > +}
> > > > +
> > > > +/* Public entrypoint.  See description in libgccjit.h.
> > > > +
> > > > +   After error-checking, the real work is done by the
> > > > +   gcc::jit::recording::type::dyn_cast_function_type method,
> > > > in
> > > > +   jit-recording.c.  */
> > > > +
> > > > +gcc_jit_function_type *
> > > > +gcc_jit_type_is_function_ptr_type (gcc_jit_type *type)
> > > > +{
> > > > +  RETURN_NULL_IF_FAIL (type, NULL, NULL, "NULL type");
> > > > +  gcc::jit::recording::type *func_ptr_type = type->dereference
> > > > ();
> > > > +  RETURN_NULL_IF_FAIL (func_ptr_type, NULL, NULL, "NULL
> > > > type");
> > > > +  gcc::jit::recording::function_type *func_type =
> > > > +    func_ptr_type->dyn_cast_function_type ();
> > > > +  RETURN_NULL_IF_FAIL (func_type, NULL, NULL, "NULL type");
> > > 
> > > I notice that the other new "*_is_*" functions don't fail if the
> > > dyncast returns NULL, whereas this one does.
> > > 
> > > RETURN_NULL_IF_FAIL calls jit_error; do we really want that?  It
> > > seems
> > > more consistent to have it return NULL without an error for the
> > > case
> > > where "type" isn't a function ptr type.
> > > 
> > > > +
> > > > +  return (gcc_jit_function_type *)func_type;
> > > > +}
> > > > +
> > > > +/* Public entrypoint.  See description in libgccjit.h.
> > > > +
> > > > +   After error-checking, the real work is done by the
> > > > +   gcc::jit::recording::function_type::get_return_type method,
> > > > in
> > > > +   jit-recording.c.  */
> > > > +
> > > > +gcc_jit_type *
> > > > +gcc_jit_function_type_get_return_type (gcc_jit_function_type
> > > > *function_type)
> > > > +{
> > > > +  RETURN_NULL_IF_FAIL (function_type, NULL, NULL, "NULL
> > > > struct_type");
> > > 
> > > Wrong error message; should be "NULL function_type".
> > > 
> > > 
> > > > +  return (gcc_jit_type *)function_type->get_return_type ();
> > > > +}
> > > > +
> > > > +/* Public entrypoint.  See description in libgccjit.h.
> > > > +
> > > > +   After error-checking, the real work is done by the
> > > > +   gcc::jit::recording::function_type::get_param_types method,
> > > > in
> > > > +   jit-recording.c.  */
> > > > +
> > > > +ssize_t
> > > > +gcc_jit_function_type_get_param_count (gcc_jit_function_type
> > > > *function_type)
> > > > +{
> > > > +  RETURN_VAL_IF_FAIL (function_type, -1, NULL, NULL, "NULL
> > > > struct_type");
> > > 
> > > Wrong error message; should be "NULL function_type".
> > > 
> > > > +  return function_type->get_param_types ().length ();
> > > > +}
> > > > +
> > > > +/* Public entrypoint.  See description in libgccjit.h.
> > > > +
> > > > +   After error-checking, the real work is done by the
> > > > +   gcc::jit::recording::function_type::get_param_types method,
> > > > in
> > > > +   jit-recording.c.  */
> > > > +
> > > > +gcc_jit_type *
> > > > +gcc_jit_function_type_get_param_type (gcc_jit_function_type
> > > > *function_type,
> > > > +                               int index)
> > > > +{
> > > > +  RETURN_NULL_IF_FAIL (function_type, NULL, NULL, "NULL
> > > > struct_type");
> > > 
> > > Wrong error message; should be "NULL function_type".
> > > 
> > > 
> > > > +  int num_params = function_type->get_param_types ().length
> > > > ();
> > > > +  gcc::jit::recording::context *ctxt = function_type->m_ctxt;
> > > 
> > > "index" should either be unsigned, or we need to check here for
> > > >= 0.
> > > 
> > > > +  RETURN_NULL_IF_FAIL_PRINTF3 (index < num_params,
> > > > +                              ctxt, NULL,
> > > > +                              "index of %d is too large (%s
> > > > has %d
> > > > params)",
> > > > +                              index,
> > > > +                              function_type->get_debug_string
> > > > (),
> > > > +                              num_params);
> > > > +  return (gcc_jit_type *)function_type->get_param_types
> > > > ()[index];
> > > > +}
> > > > +
> > > >  /* Public entrypoint.  See description in libgccjit.h.
> > > >  
> > > >     After error-checking, the real work is done by the
> > > > @@ -731,6 +930,36 @@ gcc_jit_struct_set_fields (gcc_jit_struct
> > > > *struct_type,
> > > >                            (gcc::jit::recording::field
> > > > **)fields);
> > > >  }
> > > >  
> > > > +
> > > > +/* Public entrypoint.  See description in libgccjit.h.
> > > > +
> > > > +   After error-checking, the real work is done by the
> > > > +   gcc::jit::recording::fields::get_field method in
> > > > +   jit-recording.c.  */
> > > > +extern gcc_jit_field *
> > > > +gcc_jit_struct_get_field (gcc_jit_struct *struct_type,
> > > > +                          int index)
> > > > +{
> > > > +  RETURN_NULL_IF_FAIL (struct_type, NULL, NULL, "NULL struct
> > > > type");
> > > > +  RETURN_NULL_IF_FAIL (struct_type->get_fields (), NULL, NULL,
> > > > "NULL
> > > > struct fields");
> > > 
> > > "index" should either be unsigned, or we need to check here for
> > > >= 0.
> > > 
> > > > +  RETURN_NULL_IF_FAIL (index < struct_type->get_fields ()-
> > > > >length
> > > > (), NULL,
> > > > +                               NULL, "NULL struct type");
> > > > +  return (gcc_jit_field *)struct_type->get_fields ()-
> > > > >get_field
> > > > (index);
> > > > +}
> > > 
> > > [...snip...]
> > > 
> > > > diff --git a/gcc/jit/libgccjit.h b/gcc/jit/libgccjit.h
> > > > index 7134841bb07..db4ccffb41c 100644
> > > > --- a/gcc/jit/libgccjit.h
> > > > +++ b/gcc/jit/libgccjit.h
> > > > @@ -96,6 +96,12 @@ typedef struct gcc_jit_field gcc_jit_field;
> > > >     the layout for, or an opaque type.  */
> > > >  typedef struct gcc_jit_struct gcc_jit_struct;
> > > >  
> > > > +/* A gcc_jit_function_type encapsulates a function type.  */
> > > > +typedef struct gcc_jit_function_type gcc_jit_function_type;
> > > > +
> > > > +/* A gcc_jit_vector_type encapsulates a vector type.  */
> > > > +typedef struct gcc_jit_vector_type gcc_jit_vector_type;
> > > > +
> > > 
> > > Please add these to the ASCII art inheritance diagram immediately
> > > above:
> > >   typedef struct gcc_jit_object gcc_jit_object;
> > > 
> > > [...snip...]
> > > 
> > > >  /* Unions work similarly to structs.  */
> > > >  extern gcc_jit_type *
> > > >  gcc_jit_context_new_union_type (gcc_jit_context *ctxt,
> > > > @@ -1518,6 +1533,78 @@ gcc_jit_version_minor (void);
> > > >  extern int
> > > >  gcc_jit_version_patchlevel (void);
> > > >  
> > > > +#define LIBGCCJIT_HAVE_REFLECTION
> > > > +
> > > > +/* Reflection functions to get the number of parameters,
> > > > return
> > > > type
> > > > of
> > > > +   a function and whether a type is a bool from the C API.
> > > > +
> > > > +   This API entrypoint was added in LIBGCCJIT_ABI_15; you can
> > > > test
> > > > for its
> > > > +   presence using
> > > > +     #ifdef LIBGCCJIT_HAVE_REFLECTION
> > > > +*/
> > > > +/* Get the return type of a function.  */
> > > > +extern gcc_jit_type *
> > > > +gcc_jit_function_get_return_type (gcc_jit_function *func);
> > > > +
> > > > +/* Get the number of params of a function.  */
> > > > +extern ssize_t
> > > > +gcc_jit_function_get_param_count (gcc_jit_function *func);
> > > 
> > > You're using ssize_t here, why?  Wouldn't size_t be better?
> > > The count can't be negative.
> > > 
> > > Should we use size_t for indexes, rather than "int"?
> > > 
> > > (this happens in various places e.g.
> > > gcc_jit_function_type_get_param_count and
> > > gcc_jit_vector_type_get_num_units)
> > > 
> > > [...snip...]
> > > 
> > > > diff --git a/gcc/jit/libgccjit.map b/gcc/jit/libgccjit.map
> > > > index a6e67e781a4..720b6ca286f 100644
> > > > --- a/gcc/jit/libgccjit.map
> > > > +++ b/gcc/jit/libgccjit.map
> > > > @@ -192,3 +192,24 @@ LIBGCCJIT_ABI_14 {
> > > >    global:
> > > >      gcc_jit_global_set_initializer;
> > > >  } LIBGCCJIT_ABI_13;
> > > > +
> > > > +LIBGCCJIT_ABI_15 {
> > > > +  global:
> > > > +    gcc_jit_function_get_return_type;
> > > > +    gcc_jit_function_get_param_count;
> > > > +    gcc_jit_function_type_get_return_type;
> > > > +    gcc_jit_function_type_get_param_count;
> > > > +    gcc_jit_function_type_get_param_type;
> > > > +    gcc_jit_type_unqualified;
> > > > +    gcc_jit_type_is_array;
> > > > +    gcc_jit_type_is_bool;
> > > > +    gcc_jit_type_is_function_ptr_type;
> > > > +    gcc_jit_type_is_integral;
> > > > +    gcc_jit_type_is_pointer;
> > > > +    gcc_jit_type_is_vector;
> > > > +    gcc_jit_vector_type_get_element_type;
> > > > +    gcc_jit_vector_type_get_num_units;
> > > > +    gcc_jit_struct_get_field;
> > > > +    gcc_jit_type_is_struct;
> > > > +    gcc_jit_struct_get_field_count;
> > > > +} LIBGCCJIT_ABI_14;
> > > 
> > > As noted above, this will need to be LIBGCCJIT_ABI_16 as I used
> > > LIBGCCJIT_ABI_15 for inline asm.
> > > 
> > > [...snip...]
> > > 
> > > > diff --git a/gcc/testsuite/jit.dg/test-reflection.c
> > > > b/gcc/testsuite/jit.dg/test-reflection.c
> > > > new file mode 100644
> > > > index 00000000000..b3cf2942f3a
> > > > --- /dev/null
> > > > +++ b/gcc/testsuite/jit.dg/test-reflection.c
> > > > @@ -0,0 +1,89 @@
> > > > +#include <stdlib.h>
> > > > +#include <stdio.h>
> > > > +
> > > > +#include "libgccjit.h"
> > > > +
> > > > +#include "harness.h"
> > > > +
> > > > +void
> > > > +create_code (gcc_jit_context *ctxt, void *user_data)
> > > > +{
> > > > +  /* Do nothing.  */
> > > > +}
> > > > +
> > > > +void
> > > > +verify_code (gcc_jit_context *ctxt, gcc_jit_result *result)
> > > > +{
> > > > +  /* Get the built-in functions.  */
> > > > +  gcc_jit_function *builtin_sin =
> > > > +    gcc_jit_context_get_builtin_function (ctxt, "sin");
> > > > +
> > > > +  CHECK_VALUE (gcc_jit_function_get_param_count(builtin_sin),
> > > > 1);
> > > > +
> > > > +  gcc_jit_type *double_type =
> > > > +    gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_DOUBLE);
> > > > +  CHECK_VALUE (gcc_jit_function_get_return_type(builtin_sin),
> > > > double_type);
> > > > +  CHECK (!gcc_jit_type_is_integral(double_type));
> > > > +
> > > > +  gcc_jit_type *bool_type =
> > > > +    gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_BOOL);
> > > > +  CHECK (gcc_jit_type_is_bool(bool_type));
> > > > +  CHECK (!gcc_jit_type_is_integral(bool_type));
> > > > +
> > > > +  gcc_jit_type *aligned_bool_type =
> > > > +    gcc_jit_type_get_aligned(gcc_jit_context_get_type (ctxt,
> > > > GCC_JIT_TYPE_BOOL), 8);
> > > > +  CHECK (gcc_jit_type_is_bool(aligned_bool_type));
> > > > +  CHECK (bool_type != aligned_bool_type);
> > > > +  CHECK_VALUE (gcc_jit_type_unqualified(aligned_bool_type),
> > > > bool_type);
> > > > +
> > > > +  CHECK_VALUE
> > > > (gcc_jit_type_unqualified(gcc_jit_type_get_const(bool_type)),
> > > > bool_type);
> > > > +  CHECK_VALUE
> > > > (gcc_jit_type_unqualified(gcc_jit_type_get_volatile(bool_type))
> > > > ,
> > > > bool_type);
> > > > +
> > > > +  gcc_jit_type *int64 =
> > > > +    gcc_jit_context_get_int_type(ctxt, 8, 1);
> > > > +  CHECK (gcc_jit_type_is_integral(int64));
> > > > +  gcc_jit_type *uint64 =
> > > > +    gcc_jit_context_get_int_type(ctxt, 8, 0);
> > > > +  CHECK (gcc_jit_type_is_integral(uint64));
> > > > +  gcc_jit_type *int8 =
> > > > +    gcc_jit_context_get_int_type(ctxt, 1, 1);
> > > > +  CHECK (gcc_jit_type_is_integral(int8));
> > > > +  gcc_jit_type *uint8 =
> > > > +    gcc_jit_context_get_int_type(ctxt, 1, 0);
> > > > +  CHECK (gcc_jit_type_is_integral(uint8));
> > > > +
> > > > +  CHECK (!gcc_jit_type_is_vector(double_type));
> > > > +  gcc_jit_type *vec_type = gcc_jit_type_get_vector
> > > > (double_type,
> > > > 4);
> > > > +  gcc_jit_vector_type *vector_type =
> > > > gcc_jit_type_is_vector(vec_type);
> > > > +  CHECK (vector_type);
> > > > +  CHECK (vec_type != double_type);
> > > > +  CHECK_VALUE
> > > > (gcc_jit_vector_type_get_element_type(vector_type),
> > > > double_type);
> > > > +  CHECK_VALUE (gcc_jit_vector_type_get_num_units(vector_type),
> > > > 4);
> > > > +
> > > > +  CHECK (!gcc_jit_type_is_pointer(double_type));
> > > > +  CHECK_VALUE
> > > > (gcc_jit_type_is_pointer(gcc_jit_type_get_pointer(double_type))
> > > > ,
> > > > double_type);
> > > > +
> > > > +  gcc_jit_type* params[2] = {int8, uint64};
> > > > +  gcc_jit_type *function_ptr_type =
> > > > gcc_jit_context_new_function_ptr_type(ctxt, NULL, int64, 2,
> > > > params,
> > > > 0);
> > > > +  gcc_jit_function_type *function_type =
> > > > gcc_jit_type_is_function_ptr_type (function_ptr_type);
> > > > +  CHECK (function_type);
> > > > +  int param_count =
> > > > gcc_jit_function_type_get_param_count(function_type);
> > > > +  CHECK_VALUE (param_count, 2);
> > > > +  gcc_jit_type *return_type =
> > > > gcc_jit_function_type_get_return_type(function_type);
> > > > +  CHECK_VALUE (return_type, int64);
> > > > +  gcc_jit_type *param1 =
> > > > gcc_jit_function_type_get_param_type(function_type, 0);
> > > > +  CHECK_VALUE (param1, int8);
> > > > +  gcc_jit_type *param2 =
> > > > gcc_jit_function_type_get_param_type(function_type, 1);
> > > > +  CHECK_VALUE (param2, uint64);
> > > > +
> > > > +  gcc_jit_field *field1 = gcc_jit_context_new_field (ctxt,
> > > > NULL,
> > > > uint64, "field1");
> > > > +  gcc_jit_field *field2 = gcc_jit_context_new_field (ctxt,
> > > > NULL,
> > > > double_type, "field2");
> > > > +  gcc_jit_field *fields[2] = { field1, field2 };
> > > > +  gcc_jit_struct *struct_type =
> > > > gcc_jit_context_new_struct_type
> > > > (ctxt, NULL, "testStruct", 2, fields);
> > > > +  CHECK_VALUE (gcc_jit_struct_get_field_count(struct_type),
> > > > 2);
> > > > +  CHECK_VALUE (gcc_jit_struct_get_field(struct_type, 0),
> > > > field1);
> > > > +  CHECK_VALUE (gcc_jit_struct_get_field(struct_type, 1),
> > > > field2);
> > > > +  gcc_jit_struct *struct_ty =
> > > > gcc_jit_type_is_struct(gcc_jit_struct_as_type(struct_type));
> > > > +  CHECK_VALUE (struct_ty, struct_type);
> > > 
> > > 
> > > I think this is missing test coverage for the various
> > > gcc_jit_type_is_*
> > > entrypoints gracefully returning NULL when the type passed to
> > > them is
> > > wrong (e.g. a non-struct type passed to gcc_jit_type_is_struct,
> > > etc)
> > > 
> > > Hope this is constructive; sorry again about the delay in
> > > reviewing
> > > it.
> > > Dave
> > > 
> > > 
> > 
> > 
> 
> 


[-- Attachment #2: 0001-This-patch-add-some-reflection-functions-in-the-jit-.patch --]
[-- Type: text/x-patch, Size: 31282 bytes --]

From bf0d476b679ae7cdb21b7dd00199534454376678 Mon Sep 17 00:00:00 2001
From: Antoni Boucher <bouanto@zoho.com>
Date: Sat, 1 Aug 2020 17:52:17 -0400
Subject: [PATCH] This patch add some reflection functions in the jit C api
 [PR96889]

2020-09-1  Antoni Boucher  <bouanto@zoho.com>

    gcc/jit/
            PR target/96889
            * docs/topics/compatibility.rst (LIBGCCJIT_ABI_16): New ABI tag.
            * docs/topics/functions.rst: Add documentation for the
            functions gcc_jit_function_get_return_type and
            gcc_jit_function_get_param_count
            * docs/topics/types.rst: Add documentation for the functions
            gcc_jit_function_type_get_return_type,
            gcc_jit_function_type_get_param_count,
            gcc_jit_function_type_get_param_type,
            gcc_jit_type_unqualified, gcc_jit_type_dyncast_array,
            gcc_jit_type_is_bool,
            gcc_jit_type_dyncast_function_ptr_type,
            gcc_jit_type_is_integral, gcc_jit_type_is_pointer,
            gcc_jit_type_dyncast_vector,
            gcc_jit_vector_type_get_element_type,
            gcc_jit_vector_type_get_num_units,
            gcc_jit_struct_get_field, gcc_jit_type_is_struct,
            and gcc_jit_struct_get_field_count
            * libgccjit.c:
            (gcc_jit_function_get_return_type, gcc_jit_function_get_param_count,
            gcc_jit_function_type_get_return_type,
            gcc_jit_function_type_get_param_count,
            gcc_jit_function_type_get_param_type, gcc_jit_type_unqualified,
            gcc_jit_type_dyncast_array, gcc_jit_type_is_bool,
            gcc_jit_type_dyncast_function_ptr_type, gcc_jit_type_is_integral,
            gcc_jit_type_is_pointer, gcc_jit_type_dyncast_vector,
            gcc_jit_vector_type_get_element_type,
            gcc_jit_vector_type_get_num_units, gcc_jit_struct_get_field,
            gcc_jit_type_is_struct, gcc_jit_struct_get_field_count): New
            functions.
            (struct gcc_jit_function_type, struct gcc_jit_vector_type):
            New types.
            * libgccjit.h:
            (gcc_jit_function_get_return_type, gcc_jit_function_get_param_count,
            gcc_jit_function_type_get_return_type,
            gcc_jit_function_type_get_param_count,
            gcc_jit_function_type_get_param_type, gcc_jit_type_unqualified,
            gcc_jit_type_dyncast_array, gcc_jit_type_is_bool,
            gcc_jit_type_dyncast_function_ptr_type, gcc_jit_type_is_integral,
            gcc_jit_type_is_pointer, gcc_jit_type_dyncast_vector,
            gcc_jit_vector_type_get_element_type,
            gcc_jit_vector_type_get_num_units, gcc_jit_struct_get_field,
            gcc_jit_type_is_struct, gcc_jit_struct_get_field_count): New
            function declarations.
            (struct gcc_jit_function_type, struct gcc_jit_vector_type):
            New types.
            * jit-recording.h: New functions (is_struct and is_vector)
            * libgccjit.map (LIBGCCJIT_ABI_16): New ABI tag.

    gcc/testsuite/
            PR target/96889
            * jit.dg/all-non-failing-tests.h: Add test-reflection.c.
            * jit.dg/test-reflection.c: New test.
---
 gcc/jit/docs/topics/compatibility.rst        |  43 +++-
 gcc/jit/docs/topics/functions.rst            |  26 ++
 gcc/jit/docs/topics/types.rst                | 122 +++++++++
 gcc/jit/jit-recording.h                      |   7 +
 gcc/jit/libgccjit.c                          | 256 +++++++++++++++++++
 gcc/jit/libgccjit.h                          |  89 +++++++
 gcc/jit/libgccjit.map                        |  21 ++
 gcc/testsuite/jit.dg/all-non-failing-tests.h |  10 +
 gcc/testsuite/jit.dg/test-reflection.c       |  95 +++++++
 9 files changed, 668 insertions(+), 1 deletion(-)
 create mode 100644 gcc/testsuite/jit.dg/test-reflection.c

diff --git a/gcc/jit/docs/topics/compatibility.rst b/gcc/jit/docs/topics/compatibility.rst
index 239b6aa1a92..cec40ca508c 100644
--- a/gcc/jit/docs/topics/compatibility.rst
+++ b/gcc/jit/docs/topics/compatibility.rst
@@ -230,7 +230,7 @@ entrypoints:
 .. _LIBGCCJIT_ABI_15:
 
 ``LIBGCCJIT_ABI_15``
------------------------
+--------------------
 ``LIBGCCJIT_ABI_15`` covers the addition of API entrypoints for directly
 embedding assembler instructions:
 
@@ -243,3 +243,44 @@ embedding assembler instructions:
   * :func:`gcc_jit_extended_asm_add_input_operand`
   * :func:`gcc_jit_extended_asm_add_clobber`
   * :func:`gcc_jit_context_add_top_level_asm`
+
+.. _LIBGCCJIT_ABI_16:
+
+``LIBGCCJIT_ABI_16``
+--------------------
+``LIBGCCJIT_ABI_16`` covers the addition of reflection functions via API
+entrypoints:
+
+  * :func:`gcc_jit_function_get_return_type`
+
+  * :func:`gcc_jit_function_get_param_count`
+
+  * :func:`gcc_jit_type_is_array`
+
+  * :func:`gcc_jit_type_is_bool`
+
+  * :func:`gcc_jit_type_is_integral`
+
+  * :func:`gcc_jit_type_is_pointer`
+
+  * :func:`gcc_jit_type_is_struct`
+
+  * :func:`gcc_jit_type_is_vector`
+
+  * :func:`gcc_jit_type_unqualified`
+
+  * :func:`gcc_jit_type_is_function_ptr_type`
+
+  * :func:`gcc_jit_function_type_get_return_type`
+
+  * :func:`gcc_jit_function_type_get_param_count`
+
+  * :func:`gcc_jit_function_type_get_param_type`
+
+  * :func:`gcc_jit_vector_type_get_num_units`
+
+  * :func:`gcc_jit_vector_type_get_element_type`
+
+  * :func:`gcc_jit_struct_get_field`
+
+  * :func:`gcc_jit_struct_get_field_count`
diff --git a/gcc/jit/docs/topics/functions.rst b/gcc/jit/docs/topics/functions.rst
index b2d9239aa0a..1d20e3045a0 100644
--- a/gcc/jit/docs/topics/functions.rst
+++ b/gcc/jit/docs/topics/functions.rst
@@ -171,6 +171,32 @@ Functions
    underlying string, so it is valid to pass in a pointer to an on-stack
    buffer.
 
+.. function::  size_t \
+               gcc_jit_function_get_param_count (gcc_jit_function *func)
+
+   Get the number of parameters of the function.
+
+.. function::  gcc_jit_type *\
+               gcc_jit_function_get_return_type (gcc_jit_function *func)
+
+   Get the return type of the function.
+
+   The API entrypoints relating to getting info about parameters and return
+   types:
+
+      * :c:func:`gcc_jit_function_get_return_type`
+
+      * :c:func:`gcc_jit_function_get_param_count`
+
+   were added in :ref:`LIBGCCJIT_ABI_15`; you can test for their presence
+   using
+
+   .. code-block:: c
+
+      #ifdef LIBGCCJIT_HAVE_REFLECTION
+
+   .. type:: gcc_jit_case
+
 Blocks
 ------
 .. type:: gcc_jit_block
diff --git a/gcc/jit/docs/topics/types.rst b/gcc/jit/docs/topics/types.rst
index 831f11b679a..1c93d638a10 100644
--- a/gcc/jit/docs/topics/types.rst
+++ b/gcc/jit/docs/topics/types.rst
@@ -345,3 +345,125 @@ Function pointer types
 
 Function pointer types can be created using
 :c:func:`gcc_jit_context_new_function_ptr_type`.
+
+Reflection API
+--------------
+
+.. function::  gcc_jit_type *\
+               gcc_jit_type_dyncast_array (gcc_jit_type *type)
+
+     Get the element type of an array type or NULL if it's not an array.
+
+.. function::  int\
+               gcc_jit_type_is_bool (gcc_jit_type *type)
+
+     Return non-zero if the type is a bool.
+
+.. function::  gcc_jit_function_type *\
+               gcc_jit_type_dyncast_function_ptr_type (gcc_jit_type *type)
+
+     Return the function type if it is one or NULL.
+
+.. function::  gcc_jit_type *\
+               gcc_jit_function_type_get_return_type (gcc_jit_function_type *function_type)
+
+     Given a function type, return its return type.
+
+.. function::  size_t\
+               gcc_jit_function_type_get_param_count (gcc_jit_function_type *function_type)
+
+     Given a function type, return its number of parameters.
+
+.. function::  gcc_jit_type *\
+               gcc_jit_function_type_get_param_type (gcc_jit_function_type *function_type,
+                                                     size_t index)
+
+     Given a function type, return the type of the specified parameter.
+
+.. function::  int\
+               gcc_jit_type_is_integral (gcc_jit_type *type)
+
+     Return non-zero if the type is an integral.
+
+.. function::  gcc_jit_type *\
+               gcc_jit_type_is_pointer (gcc_jit_type *type)
+
+     Return the type pointed by the pointer type or NULL if it's not a pointer.
+
+.. function::  gcc_jit_vector_type *\
+               gcc_jit_type_dyncast_vector (gcc_jit_type *type)
+
+     Given a type, return a dynamic cast to a vector type or NULL.
+
+.. function::  gcc_jit_struct *\
+               gcc_jit_type_is_struct (gcc_jit_type *type)
+
+     Given a type, return a dynamic cast to a struct type or NULL.
+
+.. function::  size_t\
+               gcc_jit_vector_type_get_num_units (gcc_jit_vector_type *vector_type)
+
+     Given a vector type, return the number of units it contains.
+
+.. function::  gcc_jit_type *\
+               gcc_jit_vector_type_get_element_type (gcc_jit_vector_type * vector_type)
+
+     Given a vector type, return the type of its elements.
+
+.. function::  gcc_jit_type *\
+               gcc_jit_type_unqualified (gcc_jit_type *type)
+
+     Given a type, return the unqualified type, removing "const", "volatile" and
+     alignment qualifiers.
+
+.. function::  gcc_jit_field *\
+               gcc_jit_struct_get_field (gcc_jit_struct *struct_type,
+                                         size_t index)
+
+     Get a struct field by index.
+
+.. function::  size_t\
+               gcc_jit_struct_get_field_count (gcc_jit_struct *struct_type)
+
+     Get the number of fields in the struct.
+
+   The API entrypoints related to the reflection API:
+
+      * :c:func:`gcc_jit_function_type_get_return_type`
+
+      * :c:func:`gcc_jit_function_type_get_param_count`
+
+      * :c:func:`gcc_jit_function_type_get_param_type`
+
+      * :c:func:`gcc_jit_type_unqualified`
+
+      * :c:func:`gcc_jit_type_dyncast_array`
+
+      * :c:func:`gcc_jit_type_is_bool`
+
+      * :c:func:`gcc_jit_type_dyncast_function_ptr_type`
+
+      * :c:func:`gcc_jit_type_is_integral`
+
+      * :c:func:`gcc_jit_type_is_pointer`
+
+      * :c:func:`gcc_jit_type_dyncast_vector`
+
+      * :c:func:`gcc_jit_vector_type_get_element_type`
+
+      * :c:func:`gcc_jit_vector_type_get_num_units`
+
+      * :c:func:`gcc_jit_struct_get_field`
+
+      * :c:func:`gcc_jit_type_is_struct`
+
+      * :c:func:`gcc_jit_struct_get_field_count`
+
+   were added in :ref:`LIBGCCJIT_ABI_15`; you can test for their presence
+   using
+
+   .. code-block:: c
+
+      #ifdef LIBGCCJIT_HAVE_REFLECTION
+
+   .. type:: gcc_jit_case
diff --git a/gcc/jit/jit-recording.h b/gcc/jit/jit-recording.h
index 03fa1160cf0..4a994fe7094 100644
--- a/gcc/jit/jit-recording.h
+++ b/gcc/jit/jit-recording.h
@@ -546,7 +546,9 @@ public:
   virtual bool is_bool () const = 0;
   virtual type *is_pointer () = 0;
   virtual type *is_array () = 0;
+  virtual struct_ *is_struct () { return NULL; }
   virtual bool is_void () const { return false; }
+  virtual vector_type *is_vector () { return NULL; }
   virtual bool has_known_size () const { return true; }
 
   bool is_numeric () const
@@ -663,6 +665,7 @@ public:
   bool is_bool () const FINAL OVERRIDE { return m_other_type->is_bool (); }
   type *is_pointer () FINAL OVERRIDE { return m_other_type->is_pointer (); }
   type *is_array () FINAL OVERRIDE { return m_other_type->is_array (); }
+  struct_ *is_struct () FINAL OVERRIDE { return m_other_type->is_struct (); }
 
 protected:
   type *m_other_type;
@@ -745,6 +748,8 @@ public:
 
   void replay_into (replayer *) FINAL OVERRIDE;
 
+  vector_type *is_vector () FINAL OVERRIDE { return this; }
+
 private:
   string * make_debug_string () FINAL OVERRIDE;
   void write_reproducer (reproducer &r) FINAL OVERRIDE;
@@ -951,6 +956,8 @@ public:
 
   const char *access_as_type (reproducer &r) FINAL OVERRIDE;
 
+  struct_ *is_struct () FINAL OVERRIDE { return this; }
+
 private:
   string * make_debug_string () FINAL OVERRIDE;
   void write_reproducer (reproducer &r) FINAL OVERRIDE;
diff --git a/gcc/jit/libgccjit.c b/gcc/jit/libgccjit.c
index 0cc650f9810..1efcabd4141 100644
--- a/gcc/jit/libgccjit.c
+++ b/gcc/jit/libgccjit.c
@@ -60,6 +60,14 @@ struct gcc_jit_struct : public gcc::jit::recording::struct_
 {
 };
 
+struct gcc_jit_function_type : public gcc::jit::recording::function_type
+{
+};
+
+struct gcc_jit_vector_type : public gcc::jit::recording::vector_type
+{
+};
+
 struct gcc_jit_field : public gcc::jit::recording::field
 {
 };
@@ -515,6 +523,194 @@ gcc_jit_type_get_volatile (gcc_jit_type *type)
   return (gcc_jit_type *)type->get_volatile ();
 }
 
+/* Public entrypoint.  See description in libgccjit.h.
+
+   After error-checking, the real work is done by the
+   gcc::jit::recording::type::is_array method, in
+   jit-recording.c.  */
+
+gcc_jit_type *
+gcc_jit_type_dyncast_array (gcc_jit_type *type)
+{
+  RETURN_NULL_IF_FAIL (type, NULL, NULL, "NULL type");
+
+  return (gcc_jit_type *)type->is_array ();
+}
+
+/* Public entrypoint.  See description in libgccjit.h.
+
+   After error-checking, the real work is done by the
+   gcc::jit::recording::type::is_bool method, in
+   jit-recording.c.  */
+
+int
+gcc_jit_type_is_bool (gcc_jit_type *type)
+{
+  RETURN_VAL_IF_FAIL (type, FALSE, NULL, NULL, "NULL type");
+
+  return type->is_bool ();
+}
+
+/* Public entrypoint.  See description in libgccjit.h.
+
+   After error-checking, the real work is done by the
+   gcc::jit::recording::type::is_pointer method, in
+   jit-recording.c.  */
+
+gcc_jit_type *
+gcc_jit_type_is_pointer (gcc_jit_type *type)
+{
+  RETURN_NULL_IF_FAIL (type, NULL, NULL, "NULL type");
+
+  return (gcc_jit_type *)type->is_pointer ();
+}
+
+/* Public entrypoint.  See description in libgccjit.h.
+
+   After error-checking, the real work is done by the
+   gcc::jit::recording::type::is_int method, in
+   jit-recording.c.  */
+
+int
+gcc_jit_type_is_integral (gcc_jit_type *type)
+{
+  RETURN_VAL_IF_FAIL (type, FALSE, NULL, NULL, "NULL type");
+
+  return type->is_int ();
+}
+
+/* Public entrypoint.  See description in libgccjit.h.
+
+   After error-checking, the real work is done by the
+   gcc::jit::recording::type::is_vector method, in
+   jit-recording.c.  */
+
+gcc_jit_vector_type *
+gcc_jit_type_dyncast_vector (gcc_jit_type *type)
+{
+  RETURN_NULL_IF_FAIL (type, NULL, NULL, "NULL type");
+  gcc::jit::recording::vector_type *vector_type = type->is_vector ();
+  return (gcc_jit_vector_type *)vector_type;
+}
+
+/* Public entrypoint.  See description in libgccjit.h.
+
+   After error-checking, the real work is done by the
+   gcc::jit::recording::type::is_struct method, in
+   jit-recording.c.  */
+
+gcc_jit_struct *
+gcc_jit_type_is_struct (gcc_jit_type *type)
+{
+  RETURN_NULL_IF_FAIL (type, NULL, NULL, "NULL type");
+  gcc::jit::recording::struct_ *struct_type = type->is_struct ();
+  return (gcc_jit_struct *)struct_type;
+}
+
+/* Public entrypoint.  See description in libgccjit.h.
+
+   After error-checking, the real work is done by the
+   gcc::jit::recording::vector_type::get_num_units method, in
+   jit-recording.c.  */
+
+size_t
+gcc_jit_vector_type_get_num_units (gcc_jit_vector_type *vector_type)
+{
+  RETURN_VAL_IF_FAIL (vector_type, 0, NULL, NULL, "NULL vector_type");
+  return vector_type->get_num_units ();
+}
+
+/* Public entrypoint.  See description in libgccjit.h.
+
+   After error-checking, the real work is done by the
+   gcc::jit::recording::vector_type::get_element_type method, in
+   jit-recording.c.  */
+
+gcc_jit_type *
+gcc_jit_vector_type_get_element_type (gcc_jit_vector_type *vector_type)
+{
+  RETURN_NULL_IF_FAIL (vector_type, NULL, NULL, "NULL vector_type");
+  return (gcc_jit_type *)vector_type->get_element_type ();
+}
+
+/* Public entrypoint.  See description in libgccjit.h.
+
+   After error-checking, the real work is done by the
+   gcc::jit::recording::type::unqualified method, in
+   jit-recording.c.  */
+
+gcc_jit_type *
+gcc_jit_type_unqualified (gcc_jit_type *type)
+{
+  RETURN_NULL_IF_FAIL (type, NULL, NULL, "NULL type");
+
+  return (gcc_jit_type *)type->unqualified ();
+}
+
+/* Public entrypoint.  See description in libgccjit.h.
+
+   After error-checking, the real work is done by the
+   gcc::jit::recording::type::dyn_cast_function_type method, in
+   jit-recording.c.  */
+
+gcc_jit_function_type *
+gcc_jit_type_dyncast_function_ptr_type (gcc_jit_type *type)
+{
+  RETURN_NULL_IF_FAIL (type, NULL, NULL, "NULL type");
+  gcc::jit::recording::type *func_ptr_type = type->dereference ();
+  RETURN_NULL_IF_FAIL (func_ptr_type, NULL, NULL, "NULL type");
+
+  return (gcc_jit_function_type *)func_ptr_type->dyn_cast_function_type ();
+}
+
+/* Public entrypoint.  See description in libgccjit.h.
+
+   After error-checking, the real work is done by the
+   gcc::jit::recording::function_type::get_return_type method, in
+   jit-recording.c.  */
+
+gcc_jit_type *
+gcc_jit_function_type_get_return_type (gcc_jit_function_type *function_type)
+{
+  RETURN_NULL_IF_FAIL (function_type, NULL, NULL, "NULL function_type");
+  return (gcc_jit_type *)function_type->get_return_type ();
+}
+
+/* Public entrypoint.  See description in libgccjit.h.
+
+   After error-checking, the real work is done by the
+   gcc::jit::recording::function_type::get_param_types method, in
+   jit-recording.c.  */
+
+size_t
+gcc_jit_function_type_get_param_count (gcc_jit_function_type *function_type)
+{
+  RETURN_VAL_IF_FAIL (function_type, 0, NULL, NULL, "NULL function_type");
+  return function_type->get_param_types ().length ();
+}
+
+/* Public entrypoint.  See description in libgccjit.h.
+
+   After error-checking, the real work is done by the
+   gcc::jit::recording::function_type::get_param_types method, in
+   jit-recording.c.  */
+
+gcc_jit_type *
+gcc_jit_function_type_get_param_type (gcc_jit_function_type *function_type,
+				size_t index)
+{
+  RETURN_NULL_IF_FAIL (function_type, NULL, NULL, "NULL function_type");
+  size_t num_params = function_type->get_param_types ().length ();
+  gcc::jit::recording::context *ctxt = function_type->m_ctxt;
+  RETURN_NULL_IF_FAIL_PRINTF3 (index < num_params,
+			       ctxt, NULL,
+			       "index of %ld is too large (%s has %ld params)",
+			       index,
+			       function_type->get_debug_string (),
+			       num_params);
+  return (gcc_jit_type *)function_type->get_param_types ()[index];
+}
+
 /* Public entrypoint.  See description in libgccjit.h.
 
    After error-checking, the real work is done by the
@@ -736,6 +932,37 @@ gcc_jit_struct_set_fields (gcc_jit_struct *struct_type,
 			   (gcc::jit::recording::field **)fields);
 }
 
+
+/* Public entrypoint.  See description in libgccjit.h.
+
+   After error-checking, the real work is done by the
+   gcc::jit::recording::fields::get_field method in
+   jit-recording.c.  */
+extern gcc_jit_field *
+gcc_jit_struct_get_field (gcc_jit_struct *struct_type,
+			   size_t index)
+{
+  RETURN_NULL_IF_FAIL (struct_type, NULL, NULL, "NULL struct type");
+  RETURN_NULL_IF_FAIL (struct_type->get_fields (), NULL, NULL,
+				"NULL struct fields");
+  RETURN_NULL_IF_FAIL ((int) index < struct_type->get_fields ()->length (),
+				NULL, NULL, "NULL struct type");
+  return (gcc_jit_field *)struct_type->get_fields ()->get_field (index);
+}
+
+/* Public entrypoint.  See description in libgccjit.h.
+
+   After error-checking, this calls the trivial
+   gcc::jit::recording::struct_::get_fields method in
+   jit-recording.h.  */
+
+size_t
+gcc_jit_struct_get_field_count (gcc_jit_struct *struct_type)
+{
+  RETURN_VAL_IF_FAIL (struct_type, 0, NULL, NULL, "NULL struct type");
+  return struct_type->get_fields ()->length ();
+}
+
 /* Public entrypoint.  See description in libgccjit.h.
 
    After error-checking, the real work is done by the
@@ -1017,6 +1244,35 @@ gcc_jit_function_get_param (gcc_jit_function *func, int index)
   return static_cast <gcc_jit_param *> (func->get_param (index));
 }
 
+/* Public entrypoint.  See description in libgccjit.h.
+
+   After error-checking, the real work is done by the
+   gcc::jit::recording::function::get_params method, in
+   jit-recording.h.
+  */
+
+size_t
+gcc_jit_function_get_param_count (gcc_jit_function *func)
+{
+  RETURN_VAL_IF_FAIL (func, 0, NULL, NULL, "NULL function");
+  gcc::jit::recording::context *ctxt = func->m_ctxt;
+  JIT_LOG_FUNC (ctxt->get_logger ());
+  return func->get_params ().length ();
+}
+
+/* Public entrypoint.  See description in libgccjit.h.
+
+   After error-checking, the real work is done by the
+   gcc::jit::recording::function::get_return_type method, in
+   jit-recording.h.  */
+
+gcc_jit_type *
+gcc_jit_function_get_return_type (gcc_jit_function *func)
+{
+    RETURN_NULL_IF_FAIL (func, NULL, NULL, "NULL function_type");
+    return (gcc_jit_type *)func->get_return_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 5c722c2c57f..5025d91802a 100644
--- a/gcc/jit/libgccjit.h
+++ b/gcc/jit/libgccjit.h
@@ -61,6 +61,8 @@ typedef struct gcc_jit_result gcc_jit_result;
 	 +- gcc_jit_location
 	 +- gcc_jit_type
 	    +- gcc_jit_struct
+	    +- gcc_jit_function_type
+	    +- gcc_jit_vector_type
 	 +- gcc_jit_field
 	 +- gcc_jit_function
 	 +- gcc_jit_block
@@ -97,6 +99,12 @@ typedef struct gcc_jit_field gcc_jit_field;
    the layout for, or an opaque type.  */
 typedef struct gcc_jit_struct gcc_jit_struct;
 
+/* A gcc_jit_function_type encapsulates a function type.  */
+typedef struct gcc_jit_function_type gcc_jit_function_type;
+
+/* A gcc_jit_vector_type encapsulates a vector type.  */
+typedef struct gcc_jit_vector_type gcc_jit_vector_type;
+
 /* A gcc_jit_function encapsulates a function: either one that you're
    creating yourself, or a reference to one that you're dynamically
    linking to within the rest of the process.  */
@@ -654,6 +662,15 @@ gcc_jit_struct_set_fields (gcc_jit_struct *struct_type,
 			   int num_fields,
 			   gcc_jit_field **fields);
 
+/* Get a field by index.  */
+extern gcc_jit_field *
+gcc_jit_struct_get_field (gcc_jit_struct *struct_type,
+			   size_t index);
+
+/* Get the number of fields.  */
+extern size_t
+gcc_jit_struct_get_field_count (gcc_jit_struct *struct_type);
+
 /* Unions work similarly to structs.  */
 extern gcc_jit_type *
 gcc_jit_context_new_union_type (gcc_jit_context *ctxt,
@@ -1621,6 +1638,78 @@ gcc_jit_context_add_top_level_asm (gcc_jit_context *ctxt,
 				   gcc_jit_location *loc,
 				   const char *asm_stmts);
 
+#define LIBGCCJIT_HAVE_REFLECTION
+
+/* Reflection functions to get the number of parameters, return type of
+   a function and whether a type is a bool from the C API.
+
+   This API entrypoint was added in LIBGCCJIT_ABI_15; you can test for its
+   presence using
+     #ifdef LIBGCCJIT_HAVE_REFLECTION
+*/
+/* Get the return type of a function.  */
+extern gcc_jit_type *
+gcc_jit_function_get_return_type (gcc_jit_function *func);
+
+/* Get the number of params of a function.  */
+extern size_t
+gcc_jit_function_get_param_count (gcc_jit_function *func);
+
+/* Get the element type of an array type or NULL if it's not an array.  */
+extern gcc_jit_type *
+gcc_jit_type_dyncast_array (gcc_jit_type *type);
+
+/* Return non-zero if the type is a bool.  */
+extern int
+gcc_jit_type_is_bool (gcc_jit_type *type);
+
+/* Return the function type if it is one or NULL.  */
+extern gcc_jit_function_type *
+gcc_jit_type_dyncast_function_ptr_type (gcc_jit_type *type);
+
+/* Given a function type, return its return type.  */
+extern gcc_jit_type *
+gcc_jit_function_type_get_return_type (gcc_jit_function_type *function_type);
+
+/* Given a function type, return its number of parameters.  */
+extern size_t
+gcc_jit_function_type_get_param_count (gcc_jit_function_type *function_type);
+
+/* Given a function type, return the type of the specified parameter.  */
+extern gcc_jit_type *
+gcc_jit_function_type_get_param_type (gcc_jit_function_type *function_type,
+				size_t index);
+
+/* Return non-zero if the type is an integral.  */
+extern int
+gcc_jit_type_is_integral (gcc_jit_type *type);
+
+/* Return the type pointed by the pointer type or NULL if it's not a
+ * pointer.  */
+extern gcc_jit_type *
+gcc_jit_type_is_pointer (gcc_jit_type *type);
+
+/* Given a type, return a dynamic cast to a vector type or NULL.  */
+extern gcc_jit_vector_type *
+gcc_jit_type_dyncast_vector (gcc_jit_type *type);
+
+/* Given a type, return a dynamic cast to a struct type or NULL.  */
+extern gcc_jit_struct *
+gcc_jit_type_is_struct (gcc_jit_type *type);
+
+/* Given a vector type, return the number of units it contains.  */
+extern size_t
+gcc_jit_vector_type_get_num_units (gcc_jit_vector_type *vector_type);
+
+/* Given a vector type, return the type of its elements.  */
+extern gcc_jit_type *
+gcc_jit_vector_type_get_element_type (gcc_jit_vector_type *vector_type);
+
+/* Given a type, return the unqualified type, removing "const", "volatile"
+ * and alignment qualifiers.  */
+extern gcc_jit_type *
+gcc_jit_type_unqualified (gcc_jit_type *type);
+
 #ifdef __cplusplus
 }
 #endif /* __cplusplus */
diff --git a/gcc/jit/libgccjit.map b/gcc/jit/libgccjit.map
index 337ea6c7fe4..64e790949e8 100644
--- a/gcc/jit/libgccjit.map
+++ b/gcc/jit/libgccjit.map
@@ -205,3 +205,24 @@ LIBGCCJIT_ABI_15 {
     gcc_jit_extended_asm_add_clobber;
     gcc_jit_context_add_top_level_asm;
 } LIBGCCJIT_ABI_14;
+
+LIBGCCJIT_ABI_16 {
+  global:
+    gcc_jit_function_get_return_type;
+    gcc_jit_function_get_param_count;
+    gcc_jit_function_type_get_return_type;
+    gcc_jit_function_type_get_param_count;
+    gcc_jit_function_type_get_param_type;
+    gcc_jit_type_unqualified;
+    gcc_jit_type_dyncast_array;
+    gcc_jit_type_is_bool;
+    gcc_jit_type_dyncast_function_ptr_type;
+    gcc_jit_type_is_integral;
+    gcc_jit_type_is_pointer;
+    gcc_jit_type_dyncast_vector;
+    gcc_jit_vector_type_get_element_type;
+    gcc_jit_vector_type_get_num_units;
+    gcc_jit_struct_get_field;
+    gcc_jit_type_is_struct;
+    gcc_jit_struct_get_field_count;
+} LIBGCCJIT_ABI_15;
diff --git a/gcc/testsuite/jit.dg/all-non-failing-tests.h b/gcc/testsuite/jit.dg/all-non-failing-tests.h
index 4202eb7798b..a269144d2df 100644
--- a/gcc/testsuite/jit.dg/all-non-failing-tests.h
+++ b/gcc/testsuite/jit.dg/all-non-failing-tests.h
@@ -258,6 +258,13 @@
 #undef create_code
 #undef verify_code
 
+/* test-reflection.c */
+#define create_code create_code_reflection
+#define verify_code verify_code_reflection
+#include "test-reflection.c"
+#undef create_code
+#undef verify_code
+
 /* test-string-literal.c */
 #define create_code create_code_string_literal
 #define verify_code verify_code_string_literal
@@ -424,6 +431,9 @@ const struct testcase testcases[] = {
   {"reading_struct ",
    create_code_reading_struct ,
    verify_code_reading_struct },
+  {"reflection",
+   create_code_reflection ,
+   verify_code_reflection },
   {"string_literal",
    create_code_string_literal,
    verify_code_string_literal},
diff --git a/gcc/testsuite/jit.dg/test-reflection.c b/gcc/testsuite/jit.dg/test-reflection.c
new file mode 100644
index 00000000000..112a2455c07
--- /dev/null
+++ b/gcc/testsuite/jit.dg/test-reflection.c
@@ -0,0 +1,95 @@
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "libgccjit.h"
+
+#include "harness.h"
+
+void
+create_code (gcc_jit_context *ctxt, void *user_data)
+{
+  /* Do nothing.  */
+}
+
+void
+verify_code (gcc_jit_context *ctxt, gcc_jit_result *result)
+{
+  /* Get the built-in functions.  */
+  gcc_jit_function *builtin_sin =
+    gcc_jit_context_get_builtin_function (ctxt, "sin");
+
+  CHECK_VALUE (gcc_jit_function_get_param_count(builtin_sin), 1);
+
+  gcc_jit_type *double_type =
+    gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_DOUBLE);
+  CHECK_VALUE (gcc_jit_function_get_return_type(builtin_sin), double_type);
+  CHECK (!gcc_jit_type_is_integral(double_type));
+
+  gcc_jit_type *bool_type =
+    gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_BOOL);
+  CHECK (gcc_jit_type_is_bool(bool_type));
+  CHECK (!gcc_jit_type_is_integral(bool_type));
+
+  gcc_jit_type *aligned_bool_type =
+    gcc_jit_type_get_aligned(gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_BOOL), 8);
+  CHECK (gcc_jit_type_is_bool(aligned_bool_type));
+  CHECK (bool_type != aligned_bool_type);
+  CHECK_VALUE (gcc_jit_type_unqualified(aligned_bool_type), bool_type);
+
+  CHECK_VALUE (gcc_jit_type_unqualified(gcc_jit_type_get_const(bool_type)), bool_type);
+  CHECK_VALUE (gcc_jit_type_unqualified(gcc_jit_type_get_volatile(bool_type)), bool_type);
+
+  gcc_jit_type *int64 =
+    gcc_jit_context_get_int_type(ctxt, 8, 1);
+  CHECK (gcc_jit_type_is_integral(int64));
+  gcc_jit_type *uint64 =
+    gcc_jit_context_get_int_type(ctxt, 8, 0);
+  CHECK (gcc_jit_type_is_integral(uint64));
+  gcc_jit_type *int8 =
+    gcc_jit_context_get_int_type(ctxt, 1, 1);
+  CHECK (gcc_jit_type_is_integral(int8));
+  gcc_jit_type *uint8 =
+    gcc_jit_context_get_int_type(ctxt, 1, 0);
+  CHECK (gcc_jit_type_is_integral(uint8));
+
+  CHECK (!gcc_jit_type_dyncast_vector(double_type));
+  gcc_jit_type *vec_type = gcc_jit_type_get_vector (double_type, 4);
+  gcc_jit_vector_type *vector_type = gcc_jit_type_dyncast_vector(vec_type);
+  CHECK (vector_type);
+  CHECK (vec_type != double_type);
+  CHECK_VALUE (gcc_jit_vector_type_get_element_type(vector_type), double_type);
+  CHECK_VALUE (gcc_jit_vector_type_get_num_units(vector_type), 4);
+
+  CHECK (!gcc_jit_type_is_pointer(double_type));
+  CHECK_VALUE (gcc_jit_type_is_pointer(gcc_jit_type_get_pointer(double_type)), double_type);
+
+  gcc_jit_type* params[2] = {int8, uint64};
+  gcc_jit_type *function_ptr_type = gcc_jit_context_new_function_ptr_type(ctxt, NULL, int64, 2, params, 0);
+  CHECK (!gcc_jit_type_dyncast_function_ptr_type (int64));
+  gcc_jit_function_type *function_type = gcc_jit_type_dyncast_function_ptr_type (function_ptr_type);
+  CHECK (function_type);
+  int param_count = gcc_jit_function_type_get_param_count(function_type);
+  CHECK_VALUE (param_count, 2);
+  gcc_jit_type *return_type = gcc_jit_function_type_get_return_type(function_type);
+  CHECK_VALUE (return_type, int64);
+  gcc_jit_type *param1 = gcc_jit_function_type_get_param_type(function_type, 0);
+  CHECK_VALUE (param1, int8);
+  gcc_jit_type *param2 = gcc_jit_function_type_get_param_type(function_type, 1);
+  CHECK_VALUE (param2, uint64);
+
+  gcc_jit_field *field1 = gcc_jit_context_new_field (ctxt, NULL, uint64, "field1");
+  gcc_jit_field *field2 = gcc_jit_context_new_field (ctxt, NULL, double_type, "field2");
+  gcc_jit_field *fields[2] = { field1, field2 };
+  gcc_jit_struct *struct_type = gcc_jit_context_new_struct_type (ctxt, NULL, "testStruct", 2, fields);
+  CHECK_VALUE (gcc_jit_struct_get_field_count(struct_type), 2);
+  CHECK_VALUE (gcc_jit_struct_get_field(struct_type, 0), field1);
+  CHECK_VALUE (gcc_jit_struct_get_field(struct_type, 1), field2);
+  CHECK (!gcc_jit_type_is_struct(double_type));
+  gcc_jit_struct *struct_ty = gcc_jit_type_is_struct(gcc_jit_struct_as_type(struct_type));
+  CHECK_VALUE (struct_ty, struct_type);
+
+  CHECK (!gcc_jit_type_dyncast_array(double_type));
+  gcc_jit_type* array_type = gcc_jit_context_new_array_type(ctxt, NULL, double_type, 1);
+  CHECK_VALUE (gcc_jit_type_dyncast_array(array_type), double_type);
+}
+
-- 
2.31.1


^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re: [PATCH] libgccjit: add some reflection functions in the jit C api
  2021-05-28  1:51                     ` Antoni Boucher
@ 2021-06-10 22:41                       ` David Malcolm
       [not found]                         ` <bc9e81dc3f0a68d6389c9765b5901a5dbd1dcd71.camel@zoho.com>
  0 siblings, 1 reply; 35+ messages in thread
From: David Malcolm @ 2021-06-10 22:41 UTC (permalink / raw)
  To: Antoni Boucher; +Cc: Andrea Corallo, Antoni Boucher via Jit, gcc-patches

On Thu, 2021-05-27 at 21:51 -0400, Antoni Boucher wrote:
> I chose option A, so everything is a size_t, now.
> I also renamed the dyncast functions.
> Here's the new patch.

Thanks, sorry again about the delays in reviewing your work.

You didn't specify how you tested the patch; are you running the full
jit regression test suite?

This is looking close to done; a few nits inline below:

[...snip...]

> diff --git a/gcc/jit/docs/topics/functions.rst b/gcc/jit/docs/topics/functions.rst
> index b2d9239aa0a..1d20e3045a0 100644
> --- a/gcc/jit/docs/topics/functions.rst
> +++ b/gcc/jit/docs/topics/functions.rst

[...snip...]

> +   The API entrypoints relating to getting info about parameters and return
> +   types:
> +
> +      * :c:func:`gcc_jit_function_get_return_type`
> +
> +      * :c:func:`gcc_jit_function_get_param_count`
> +
> +   were added in :ref:`LIBGCCJIT_ABI_15`; you can test for their presence
> +   using

16, rather than 15.

> +   The API entrypoints related to the reflection API:
> +
> +      * :c:func:`gcc_jit_function_type_get_return_type`
> +

[...snip...]

> +
> +      * :c:func:`gcc_jit_struct_get_field_count`
> +
> +   were added in :ref:`LIBGCCJIT_ABI_15`; you can test for their presence
> +   using

16, rather than 15 again.

> +
> +   .. code-block:: c
> +
> +      #ifdef LIBGCCJIT_HAVE_REFLECTION
> +
> +   .. type:: gcc_jit_case

[...snip...]

> +gcc_jit_type *
> +gcc_jit_function_type_get_param_type (gcc_jit_function_type *function_type,
> +				size_t index)
> +{
> +  RETURN_NULL_IF_FAIL (function_type, NULL, NULL, "NULL function_type");
> +  size_t num_params = function_type->get_param_types ().length ();
> +  gcc::jit::recording::context *ctxt = function_type->m_ctxt;
> +  RETURN_NULL_IF_FAIL_PRINTF3 (index < num_params,
> +			       ctxt, NULL,
> +			       "index of %ld is too large (%s has %ld params)",
> +			       index,
> +			       function_type->get_debug_string (),
> +			       num_params);
> +  return (gcc_jit_type *)function_type->get_param_types ()[index];
> +}
> +

I'm retaining the above, since...

[...snip...]

>  
> +
> +/* Public entrypoint.  See description in libgccjit.h.
> +
> +   After error-checking, the real work is done by the
> +   gcc::jit::recording::fields::get_field method in
> +   jit-recording.c.  */
> +extern gcc_jit_field *
> +gcc_jit_struct_get_field (gcc_jit_struct *struct_type,
> +			   size_t index)
> +{
> +  RETURN_NULL_IF_FAIL (struct_type, NULL, NULL, "NULL struct type");
> +  RETURN_NULL_IF_FAIL (struct_type->get_fields (), NULL, NULL,
> +				"NULL struct fields");
> +  RETURN_NULL_IF_FAIL ((int) index < struct_type->get_fields ()->length (),
> +				NULL, NULL, "NULL struct type");

...copy&paste error here; the message for this kind of failure needs
updating.  Do it in a similar way to how you did
gcc_jit_function_type_get_param_type above, using the ctxt of the
struct_type.

[...snip...]

> +#define LIBGCCJIT_HAVE_REFLECTION
> +
> +/* Reflection functions to get the number of parameters, return type of
> +   a function and whether a type is a bool from the C API.
> +
> +   This API entrypoint was added in LIBGCCJIT_ABI_15; you can test for its

16, rather than 15, again.

> +   presence using
> +     #ifdef LIBGCCJIT_HAVE_REFLECTION

[...snip...]

OK for trunk with the above nits fixed, assuming that you have run the
full regression test suite (or do you need help with that?)

I can't remember, sorry, do you have push rights to the gcc git
repository?

Do you have a preference as to which patch you want me to look at next?
Otherwise I'll go through them in the order in
https://github.com/antoyo/rustc_codegen_gcc/tree/master/gcc-patches

Dave



^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re: [PATCH] libgccjit: add some reflection functions in the jit C api
       [not found]                           ` <e962387aff72bce1ea29b0fc2cb04b84c26f9855.camel@redhat.com>
@ 2021-06-18 15:55                             ` Antoni Boucher
  2021-06-18 16:09                               ` David Malcolm
  0 siblings, 1 reply; 35+ messages in thread
From: Antoni Boucher @ 2021-06-18 15:55 UTC (permalink / raw)
  To: David Malcolm; +Cc: Antoni Boucher via Jit, gcc-patches

Le vendredi 11 juin 2021 à 14:00 -0400, David Malcolm a écrit :
> On Fri, 2021-06-11 at 08:15 -0400, Antoni Boucher wrote:
> > Thank you for your answer.
> > I attached the updated patch.
> 
> BTW you (or possibly me) dropped the mailing lists; was that
> deliberate?

Oh, my bad.

> > 
> > See my answers below.
> > 
> > Le jeudi 10 juin 2021 à 18:41 -0400, David Malcolm a écrit :
> > > On Thu, 2021-05-27 at 21:51 -0400, Antoni Boucher wrote:
> > > > I chose option A, so everything is a size_t, now.
> > > > I also renamed the dyncast functions.
> > > > Here's the new patch.
> > > 
> > > Thanks, sorry again about the delays in reviewing your work.
> > > 
> > > You didn't specify how you tested the patch; are you running the
> > > full
> > > jit regression test suite?
> > 
> > Yes, I run the full jit test suite.
> 
> Great.
> 
> [...snip...]
> 
> > > 
> > > I can't remember, sorry, do you have push rights to the gcc git
> > > repository?
> > 
> > I don't have push rights; it's actually my first contribution to
> > gcc.
> 
> Congratulations!  I'm excited about having Rust support for GCC (two
> different ways, in fact!)

Yup. Exciting times!

> 
> > I have signed the FSF copyright attribution.
> 
> I can push changes on your behalf, but I'd prefer it if you did it,
> especially given that you have various other patches you want to get
> in.
> 
> Instructions on how to get push rights to the git repo are here:
>   https://gcc.gnu.org/gitwrite.html
> 
> I can sponsor you.

Thanks.
I did sign up to get push rights.
Have you accepted my request to get those?

> 
> Note that your patches would still need review/approval ("Write After
> Approval").
> 
> > > Do you have a preference as to which patch you want me to look at
> > > next?
> > > Otherwise I'll go through them in the order in
> > > https://github.com/antoyo/rustc_codegen_gcc/tree/master/gcc-patches
> > 
> > You can indeed look in this directory in the order they were added.
> > There was one patch before the reflection one (0001-This-patch-
> > handles-
> > truncation-and-extension-for-cast.patch), but since it's only a
> > bugfix,
> > it doesn't matter if it's merged after.
> 
> That one looks good to me now too (I've replied on that patch).
> 
> > 
> > This one is ready for review, but I believe the other one needs
> > correction on my end since the last review you made. I'll make sure
> > to
> > fix them soon.
> 
> Now I'm confused as to which patches you're referring to, sorry. 
> I'll
> hold off for now on further reviews; let me know when you want me to
> look at them, and which ones.
> 
> Thanks
> Dave
> 



^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re: [PATCH] libgccjit: add some reflection functions in the jit C api
  2021-06-18 15:55                             ` Antoni Boucher
@ 2021-06-18 16:09                               ` David Malcolm
  2021-06-18 19:41                                 ` Antoni Boucher
  0 siblings, 1 reply; 35+ messages in thread
From: David Malcolm @ 2021-06-18 16:09 UTC (permalink / raw)
  To: Antoni Boucher; +Cc: Antoni Boucher via Jit, gcc-patches

On Fri, 2021-06-18 at 11:55 -0400, Antoni Boucher wrote:
> Le vendredi 11 juin 2021 à 14:00 -0400, David Malcolm a écrit :
> > On Fri, 2021-06-11 at 08:15 -0400, Antoni Boucher wrote:
> > > Thank you for your answer.
> > > I attached the updated patch.
> > 
> > BTW you (or possibly me) dropped the mailing lists; was that
> > deliberate?
> 
> Oh, my bad.
> 

[...]


> > 
> > 
> > > I have signed the FSF copyright attribution.
> > 
> > I can push changes on your behalf, but I'd prefer it if you did it,
> > especially given that you have various other patches you want to
> > get
> > in.
> > 
> > Instructions on how to get push rights to the git repo are here:
> >   https://gcc.gnu.org/gitwrite.html
> > 
> > I can sponsor you.
> 
> Thanks.
> I did sign up to get push rights.
> Have you accepted my request to get those?

I did, but I didn't see any kind of notification.  Did you get an email
about it?


Dave


^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re: [PATCH] libgccjit: add some reflection functions in the jit C api
  2021-06-18 16:09                               ` David Malcolm
@ 2021-06-18 19:41                                 ` Antoni Boucher
  2021-06-18 20:37                                   ` David Malcolm
  0 siblings, 1 reply; 35+ messages in thread
From: Antoni Boucher @ 2021-06-18 19:41 UTC (permalink / raw)
  To: David Malcolm; +Cc: Antoni Boucher via Jit, gcc-patches

I have write access now.
I'm not sure how I'm supposed to send my patches:
should I put it in personal branches and you'll merge them?

And for the MAINTAINERS file, should I just push to master right away,
after sending it to the mailing list?

Thanks for your help!

Le vendredi 18 juin 2021 à 12:09 -0400, David Malcolm a écrit :
> On Fri, 2021-06-18 at 11:55 -0400, Antoni Boucher wrote:
> > Le vendredi 11 juin 2021 à 14:00 -0400, David Malcolm a écrit :
> > > On Fri, 2021-06-11 at 08:15 -0400, Antoni Boucher wrote:
> > > > Thank you for your answer.
> > > > I attached the updated patch.
> > > 
> > > BTW you (or possibly me) dropped the mailing lists; was that
> > > deliberate?
> > 
> > Oh, my bad.
> > 
> 
> [...]
> 
> 
> > > 
> > > 
> > > > I have signed the FSF copyright attribution.
> > > 
> > > I can push changes on your behalf, but I'd prefer it if you did
> > > it,
> > > especially given that you have various other patches you want to
> > > get
> > > in.
> > > 
> > > Instructions on how to get push rights to the git repo are here:
> > >   https://gcc.gnu.org/gitwrite.html
> > > 
> > > I can sponsor you.
> > 
> > Thanks.
> > I did sign up to get push rights.
> > Have you accepted my request to get those?
> 
> I did, but I didn't see any kind of notification.  Did you get an
> email
> about it?
> 
> 
> Dave
> 



^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re: [PATCH] libgccjit: add some reflection functions in the jit C api
  2021-06-18 19:41                                 ` Antoni Boucher
@ 2021-06-18 20:37                                   ` David Malcolm
  2021-07-19 16:10                                     ` Antoni Boucher
  2021-09-28  0:53                                     ` Antoni Boucher
  0 siblings, 2 replies; 35+ messages in thread
From: David Malcolm @ 2021-06-18 20:37 UTC (permalink / raw)
  To: Antoni Boucher; +Cc: Antoni Boucher via Jit, gcc-patches

On Fri, 2021-06-18 at 15:41 -0400, Antoni Boucher wrote:
> I have write access now.

Great.

> I'm not sure how I'm supposed to send my patches:
> should I put it in personal branches and you'll merge them?

Please send them to this mailing list for review; once they're approved
you can merge them.

> 
> And for the MAINTAINERS file, should I just push to master right
> away,
> after sending it to the mailing list?

I think people just push the MAINTAINERS change and then let the list
know, since it makes a good test that write access is working
correctly.

Dave

> 
> Thanks for your help!
> 
> Le vendredi 18 juin 2021 à 12:09 -0400, David Malcolm a écrit :
> > On Fri, 2021-06-18 at 11:55 -0400, Antoni Boucher wrote:
> > > Le vendredi 11 juin 2021 à 14:00 -0400, David Malcolm a écrit :
> > > > On Fri, 2021-06-11 at 08:15 -0400, Antoni Boucher wrote:
> > > > > Thank you for your answer.
> > > > > I attached the updated patch.
> > > > 
> > > > BTW you (or possibly me) dropped the mailing lists; was that
> > > > deliberate?
> > > 
> > > Oh, my bad.
> > > 
> > 
> > [...]
> > 
> > 
> > > > 
> > > > 
> > > > > I have signed the FSF copyright attribution.
> > > > 
> > > > I can push changes on your behalf, but I'd prefer it if you did
> > > > it,
> > > > especially given that you have various other patches you want
> > > > to
> > > > get
> > > > in.
> > > > 
> > > > Instructions on how to get push rights to the git repo are
> > > > here:
> > > >   https://gcc.gnu.org/gitwrite.html
> > > > 
> > > > I can sponsor you.
> > > 
> > > Thanks.
> > > I did sign up to get push rights.
> > > Have you accepted my request to get those?
> > 
> > I did, but I didn't see any kind of notification.  Did you get an
> > email
> > about it?
> > 
> > 
> > Dave
> > 
> 
> 



^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re: [PATCH] libgccjit: add some reflection functions in the jit C api
  2021-06-18 20:37                                   ` David Malcolm
@ 2021-07-19 16:10                                     ` Antoni Boucher
  2021-07-29 12:59                                       ` Antoni Boucher
  2021-09-28  0:53                                     ` Antoni Boucher
  1 sibling, 1 reply; 35+ messages in thread
From: Antoni Boucher @ 2021-07-19 16:10 UTC (permalink / raw)
  To: David Malcolm; +Cc: Antoni Boucher via Jit, gcc-patches

[-- Attachment #1: Type: text/plain, Size: 2194 bytes --]

I'm sending the patch once again for review/approval.

I fixed the doc to use the new function names.

Le vendredi 18 juin 2021 à 16:37 -0400, David Malcolm a écrit :
> On Fri, 2021-06-18 at 15:41 -0400, Antoni Boucher wrote:
> > I have write access now.
> 
> Great.
> 
> > I'm not sure how I'm supposed to send my patches:
> > should I put it in personal branches and you'll merge them?
> 
> Please send them to this mailing list for review; once they're
> approved
> you can merge them.
> 
> > 
> > And for the MAINTAINERS file, should I just push to master right
> > away,
> > after sending it to the mailing list?
> 
> I think people just push the MAINTAINERS change and then let the list
> know, since it makes a good test that write access is working
> correctly.
> 
> Dave
> 
> > 
> > Thanks for your help!
> > 
> > Le vendredi 18 juin 2021 à 12:09 -0400, David Malcolm a écrit :
> > > On Fri, 2021-06-18 at 11:55 -0400, Antoni Boucher wrote:
> > > > Le vendredi 11 juin 2021 à 14:00 -0400, David Malcolm a écrit :
> > > > > On Fri, 2021-06-11 at 08:15 -0400, Antoni Boucher wrote:
> > > > > > Thank you for your answer.
> > > > > > I attached the updated patch.
> > > > > 
> > > > > BTW you (or possibly me) dropped the mailing lists; was that
> > > > > deliberate?
> > > > 
> > > > Oh, my bad.
> > > > 
> > > 
> > > [...]
> > > 
> > > 
> > > > > 
> > > > > 
> > > > > > I have signed the FSF copyright attribution.
> > > > > 
> > > > > I can push changes on your behalf, but I'd prefer it if you
> > > > > did
> > > > > it,
> > > > > especially given that you have various other patches you want
> > > > > to
> > > > > get
> > > > > in.
> > > > > 
> > > > > Instructions on how to get push rights to the git repo are
> > > > > here:
> > > > >   https://gcc.gnu.org/gitwrite.html
> > > > > 
> > > > > I can sponsor you.
> > > > 
> > > > Thanks.
> > > > I did sign up to get push rights.
> > > > Have you accepted my request to get those?
> > > 
> > > I did, but I didn't see any kind of notification.  Did you get an
> > > email
> > > about it?
> > > 
> > > 
> > > Dave
> > > 
> > 
> > 
> 
> 


[-- Attachment #2: 0001-libgccjit-Add-some-reflection-functions-PR96889.patch --]
[-- Type: text/x-patch, Size: 30879 bytes --]

From aaf77d109d74afb0f46d3e5d4d094914cb1b21de Mon Sep 17 00:00:00 2001
From: Antoni Boucher <bouanto@zoho.com>
Date: Sat, 1 Aug 2020 17:52:17 -0400
Subject: [PATCH] libgccjit: Add some reflection functions [PR96889]

2021-07-19  Antoni Boucher  <bouanto@zoho.com>

gcc/jit/
	PR target/96889
	* docs/topics/compatibility.rst (LIBGCCJIT_ABI_16): New ABI tag.
	* docs/topics/functions.rst: Add documentation for the
	functions gcc_jit_function_get_return_type and
	gcc_jit_function_get_param_count
	* docs/topics/types.rst: Add documentation for the functions
	gcc_jit_function_type_get_return_type,
	gcc_jit_function_type_get_param_count,
	gcc_jit_function_type_get_param_type,
	gcc_jit_type_unqualified, gcc_jit_type_dyncast_array,
	gcc_jit_type_is_bool,
	gcc_jit_type_dyncast_function_ptr_type,
	gcc_jit_type_is_integral, gcc_jit_type_is_pointer,
	gcc_jit_type_dyncast_vector,
	gcc_jit_vector_type_get_element_type,
	gcc_jit_vector_type_get_num_units,
	gcc_jit_struct_get_field, gcc_jit_type_is_struct,
	and gcc_jit_struct_get_field_count
	* libgccjit.c:
	(gcc_jit_function_get_return_type, gcc_jit_function_get_param_count,
	gcc_jit_function_type_get_return_type,
	gcc_jit_function_type_get_param_count,
	gcc_jit_function_type_get_param_type, gcc_jit_type_unqualified,
	gcc_jit_type_dyncast_array, gcc_jit_type_is_bool,
	gcc_jit_type_dyncast_function_ptr_type, gcc_jit_type_is_integral,
	gcc_jit_type_is_pointer, gcc_jit_type_dyncast_vector,
	gcc_jit_vector_type_get_element_type,
	gcc_jit_vector_type_get_num_units, gcc_jit_struct_get_field,
	gcc_jit_type_is_struct, gcc_jit_struct_get_field_count): New
	functions.
	(struct gcc_jit_function_type, struct gcc_jit_vector_type):
	New types.
	* libgccjit.h:
	(gcc_jit_function_get_return_type, gcc_jit_function_get_param_count,
	gcc_jit_function_type_get_return_type,
	gcc_jit_function_type_get_param_count,
	gcc_jit_function_type_get_param_type, gcc_jit_type_unqualified,
	gcc_jit_type_dyncast_array, gcc_jit_type_is_bool,
	gcc_jit_type_dyncast_function_ptr_type, gcc_jit_type_is_integral,
	gcc_jit_type_is_pointer, gcc_jit_type_dyncast_vector,
	gcc_jit_vector_type_get_element_type,
	gcc_jit_vector_type_get_num_units, gcc_jit_struct_get_field,
	gcc_jit_type_is_struct, gcc_jit_struct_get_field_count): New
	function declarations.
	(struct gcc_jit_function_type, struct gcc_jit_vector_type):
	New types.
	* jit-recording.h: New functions (is_struct and is_vector)
	* libgccjit.map (LIBGCCJIT_ABI_16): New ABI tag.

gcc/testsuite/
	PR target/96889
	* jit.dg/all-non-failing-tests.h: Add test-reflection.c.
	* jit.dg/test-reflection.c: New test.
---
 gcc/jit/docs/topics/compatibility.rst        |  43 ++-
 gcc/jit/docs/topics/functions.rst            |  26 ++
 gcc/jit/docs/topics/types.rst                | 122 +++++++++
 gcc/jit/jit-recording.h                      |   7 +
 gcc/jit/libgccjit.c                          | 261 +++++++++++++++++++
 gcc/jit/libgccjit.h                          |  89 +++++++
 gcc/jit/libgccjit.map                        |  21 ++
 gcc/testsuite/jit.dg/all-non-failing-tests.h |  10 +
 gcc/testsuite/jit.dg/test-reflection.c       |  95 +++++++
 9 files changed, 673 insertions(+), 1 deletion(-)
 create mode 100644 gcc/testsuite/jit.dg/test-reflection.c

diff --git a/gcc/jit/docs/topics/compatibility.rst b/gcc/jit/docs/topics/compatibility.rst
index 239b6aa1a92..52ee3f860a7 100644
--- a/gcc/jit/docs/topics/compatibility.rst
+++ b/gcc/jit/docs/topics/compatibility.rst
@@ -230,7 +230,7 @@ entrypoints:
 .. _LIBGCCJIT_ABI_15:
 
 ``LIBGCCJIT_ABI_15``
------------------------
+--------------------
 ``LIBGCCJIT_ABI_15`` covers the addition of API entrypoints for directly
 embedding assembler instructions:
 
@@ -243,3 +243,44 @@ embedding assembler instructions:
   * :func:`gcc_jit_extended_asm_add_input_operand`
   * :func:`gcc_jit_extended_asm_add_clobber`
   * :func:`gcc_jit_context_add_top_level_asm`
+
+.. _LIBGCCJIT_ABI_16:
+
+``LIBGCCJIT_ABI_16``
+--------------------
+``LIBGCCJIT_ABI_16`` covers the addition of reflection functions via API
+entrypoints:
+
+  * :func:`gcc_jit_function_get_return_type`
+
+  * :func:`gcc_jit_function_get_param_count`
+
+  * :func:`gcc_jit_type_dyncast_array`
+
+  * :func:`gcc_jit_type_is_bool`
+
+  * :func:`gcc_jit_type_is_integral`
+
+  * :func:`gcc_jit_type_is_pointer`
+
+  * :func:`gcc_jit_type_is_struct`
+
+  * :func:`gcc_jit_type_dyncast_vector`
+
+  * :func:`gcc_jit_type_unqualified`
+
+  * :func:`gcc_jit_type_dyncast_function_ptr_type`
+
+  * :func:`gcc_jit_function_type_get_return_type`
+
+  * :func:`gcc_jit_function_type_get_param_count`
+
+  * :func:`gcc_jit_function_type_get_param_type`
+
+  * :func:`gcc_jit_vector_type_get_num_units`
+
+  * :func:`gcc_jit_vector_type_get_element_type`
+
+  * :func:`gcc_jit_struct_get_field`
+
+  * :func:`gcc_jit_struct_get_field_count`
diff --git a/gcc/jit/docs/topics/functions.rst b/gcc/jit/docs/topics/functions.rst
index b2d9239aa0a..839934588da 100644
--- a/gcc/jit/docs/topics/functions.rst
+++ b/gcc/jit/docs/topics/functions.rst
@@ -171,6 +171,32 @@ Functions
    underlying string, so it is valid to pass in a pointer to an on-stack
    buffer.
 
+.. function::  size_t \
+               gcc_jit_function_get_param_count (gcc_jit_function *func)
+
+   Get the number of parameters of the function.
+
+.. function::  gcc_jit_type *\
+               gcc_jit_function_get_return_type (gcc_jit_function *func)
+
+   Get the return type of the function.
+
+   The API entrypoints relating to getting info about parameters and return
+   types:
+
+      * :c:func:`gcc_jit_function_get_return_type`
+
+      * :c:func:`gcc_jit_function_get_param_count`
+
+   were added in :ref:`LIBGCCJIT_ABI_16`; you can test for their presence
+   using
+
+   .. code-block:: c
+
+      #ifdef LIBGCCJIT_HAVE_REFLECTION
+
+   .. type:: gcc_jit_case
+
 Blocks
 ------
 .. type:: gcc_jit_block
diff --git a/gcc/jit/docs/topics/types.rst b/gcc/jit/docs/topics/types.rst
index 831f11b679a..6260e9afba4 100644
--- a/gcc/jit/docs/topics/types.rst
+++ b/gcc/jit/docs/topics/types.rst
@@ -345,3 +345,125 @@ Function pointer types
 
 Function pointer types can be created using
 :c:func:`gcc_jit_context_new_function_ptr_type`.
+
+Reflection API
+--------------
+
+.. function::  gcc_jit_type *\
+               gcc_jit_type_dyncast_array (gcc_jit_type *type)
+
+     Get the element type of an array type or NULL if it's not an array.
+
+.. function::  int\
+               gcc_jit_type_is_bool (gcc_jit_type *type)
+
+     Return non-zero if the type is a bool.
+
+.. function::  gcc_jit_function_type *\
+               gcc_jit_type_dyncast_function_ptr_type (gcc_jit_type *type)
+
+     Return the function type if it is one or NULL.
+
+.. function::  gcc_jit_type *\
+               gcc_jit_function_type_get_return_type (gcc_jit_function_type *function_type)
+
+     Given a function type, return its return type.
+
+.. function::  size_t\
+               gcc_jit_function_type_get_param_count (gcc_jit_function_type *function_type)
+
+     Given a function type, return its number of parameters.
+
+.. function::  gcc_jit_type *\
+               gcc_jit_function_type_get_param_type (gcc_jit_function_type *function_type,
+                                                     size_t index)
+
+     Given a function type, return the type of the specified parameter.
+
+.. function::  int\
+               gcc_jit_type_is_integral (gcc_jit_type *type)
+
+     Return non-zero if the type is an integral.
+
+.. function::  gcc_jit_type *\
+               gcc_jit_type_is_pointer (gcc_jit_type *type)
+
+     Return the type pointed by the pointer type or NULL if it's not a pointer.
+
+.. function::  gcc_jit_vector_type *\
+               gcc_jit_type_dyncast_vector (gcc_jit_type *type)
+
+     Given a type, return a dynamic cast to a vector type or NULL.
+
+.. function::  gcc_jit_struct *\
+               gcc_jit_type_is_struct (gcc_jit_type *type)
+
+     Given a type, return a dynamic cast to a struct type or NULL.
+
+.. function::  size_t\
+               gcc_jit_vector_type_get_num_units (gcc_jit_vector_type *vector_type)
+
+     Given a vector type, return the number of units it contains.
+
+.. function::  gcc_jit_type *\
+               gcc_jit_vector_type_get_element_type (gcc_jit_vector_type * vector_type)
+
+     Given a vector type, return the type of its elements.
+
+.. function::  gcc_jit_type *\
+               gcc_jit_type_unqualified (gcc_jit_type *type)
+
+     Given a type, return the unqualified type, removing "const", "volatile" and
+     alignment qualifiers.
+
+.. function::  gcc_jit_field *\
+               gcc_jit_struct_get_field (gcc_jit_struct *struct_type,
+                                         size_t index)
+
+     Get a struct field by index.
+
+.. function::  size_t\
+               gcc_jit_struct_get_field_count (gcc_jit_struct *struct_type)
+
+     Get the number of fields in the struct.
+
+   The API entrypoints related to the reflection API:
+
+      * :c:func:`gcc_jit_function_type_get_return_type`
+
+      * :c:func:`gcc_jit_function_type_get_param_count`
+
+      * :c:func:`gcc_jit_function_type_get_param_type`
+
+      * :c:func:`gcc_jit_type_unqualified`
+
+      * :c:func:`gcc_jit_type_dyncast_array`
+
+      * :c:func:`gcc_jit_type_is_bool`
+
+      * :c:func:`gcc_jit_type_dyncast_function_ptr_type`
+
+      * :c:func:`gcc_jit_type_is_integral`
+
+      * :c:func:`gcc_jit_type_is_pointer`
+
+      * :c:func:`gcc_jit_type_dyncast_vector`
+
+      * :c:func:`gcc_jit_vector_type_get_element_type`
+
+      * :c:func:`gcc_jit_vector_type_get_num_units`
+
+      * :c:func:`gcc_jit_struct_get_field`
+
+      * :c:func:`gcc_jit_type_is_struct`
+
+      * :c:func:`gcc_jit_struct_get_field_count`
+
+   were added in :ref:`LIBGCCJIT_ABI_16`; you can test for their presence
+   using
+
+   .. code-block:: c
+
+      #ifdef LIBGCCJIT_HAVE_REFLECTION
+
+   .. type:: gcc_jit_case
diff --git a/gcc/jit/jit-recording.h b/gcc/jit/jit-recording.h
index 03fa1160cf0..4a994fe7094 100644
--- a/gcc/jit/jit-recording.h
+++ b/gcc/jit/jit-recording.h
@@ -546,7 +546,9 @@ public:
   virtual bool is_bool () const = 0;
   virtual type *is_pointer () = 0;
   virtual type *is_array () = 0;
+  virtual struct_ *is_struct () { return NULL; }
   virtual bool is_void () const { return false; }
+  virtual vector_type *is_vector () { return NULL; }
   virtual bool has_known_size () const { return true; }
 
   bool is_numeric () const
@@ -663,6 +665,7 @@ public:
   bool is_bool () const FINAL OVERRIDE { return m_other_type->is_bool (); }
   type *is_pointer () FINAL OVERRIDE { return m_other_type->is_pointer (); }
   type *is_array () FINAL OVERRIDE { return m_other_type->is_array (); }
+  struct_ *is_struct () FINAL OVERRIDE { return m_other_type->is_struct (); }
 
 protected:
   type *m_other_type;
@@ -745,6 +748,8 @@ public:
 
   void replay_into (replayer *) FINAL OVERRIDE;
 
+  vector_type *is_vector () FINAL OVERRIDE { return this; }
+
 private:
   string * make_debug_string () FINAL OVERRIDE;
   void write_reproducer (reproducer &r) FINAL OVERRIDE;
@@ -951,6 +956,8 @@ public:
 
   const char *access_as_type (reproducer &r) FINAL OVERRIDE;
 
+  struct_ *is_struct () FINAL OVERRIDE { return this; }
+
 private:
   string * make_debug_string () FINAL OVERRIDE;
   void write_reproducer (reproducer &r) FINAL OVERRIDE;
diff --git a/gcc/jit/libgccjit.c b/gcc/jit/libgccjit.c
index 7fa948007ad..740e614cd1f 100644
--- a/gcc/jit/libgccjit.c
+++ b/gcc/jit/libgccjit.c
@@ -60,6 +60,14 @@ struct gcc_jit_struct : public gcc::jit::recording::struct_
 {
 };
 
+struct gcc_jit_function_type : public gcc::jit::recording::function_type
+{
+};
+
+struct gcc_jit_vector_type : public gcc::jit::recording::vector_type
+{
+};
+
 struct gcc_jit_field : public gcc::jit::recording::field
 {
 };
@@ -515,6 +523,194 @@ gcc_jit_type_get_volatile (gcc_jit_type *type)
   return (gcc_jit_type *)type->get_volatile ();
 }
 
+/* Public entrypoint.  See description in libgccjit.h.
+
+   After error-checking, the real work is done by the
+   gcc::jit::recording::type::is_array method, in
+   jit-recording.c.  */
+
+gcc_jit_type *
+gcc_jit_type_dyncast_array (gcc_jit_type *type)
+{
+  RETURN_NULL_IF_FAIL (type, NULL, NULL, "NULL type");
+
+  return (gcc_jit_type *)type->is_array ();
+}
+
+/* Public entrypoint.  See description in libgccjit.h.
+
+   After error-checking, the real work is done by the
+   gcc::jit::recording::type::is_bool method, in
+   jit-recording.c.  */
+
+int
+gcc_jit_type_is_bool (gcc_jit_type *type)
+{
+  RETURN_VAL_IF_FAIL (type, FALSE, NULL, NULL, "NULL type");
+
+  return type->is_bool ();
+}
+
+/* Public entrypoint.  See description in libgccjit.h.
+
+   After error-checking, the real work is done by the
+   gcc::jit::recording::type::is_pointer method, in
+   jit-recording.c.  */
+
+gcc_jit_type *
+gcc_jit_type_is_pointer (gcc_jit_type *type)
+{
+  RETURN_NULL_IF_FAIL (type, NULL, NULL, "NULL type");
+
+  return (gcc_jit_type *)type->is_pointer ();
+}
+
+/* Public entrypoint.  See description in libgccjit.h.
+
+   After error-checking, the real work is done by the
+   gcc::jit::recording::type::is_int method, in
+   jit-recording.c.  */
+
+int
+gcc_jit_type_is_integral (gcc_jit_type *type)
+{
+  RETURN_VAL_IF_FAIL (type, FALSE, NULL, NULL, "NULL type");
+
+  return type->is_int ();
+}
+
+/* Public entrypoint.  See description in libgccjit.h.
+
+   After error-checking, the real work is done by the
+   gcc::jit::recording::type::is_vector method, in
+   jit-recording.c.  */
+
+gcc_jit_vector_type *
+gcc_jit_type_dyncast_vector (gcc_jit_type *type)
+{
+  RETURN_NULL_IF_FAIL (type, NULL, NULL, "NULL type");
+  gcc::jit::recording::vector_type *vector_type = type->is_vector ();
+  return (gcc_jit_vector_type *)vector_type;
+}
+
+/* Public entrypoint.  See description in libgccjit.h.
+
+   After error-checking, the real work is done by the
+   gcc::jit::recording::type::is_struct method, in
+   jit-recording.c.  */
+
+gcc_jit_struct *
+gcc_jit_type_is_struct (gcc_jit_type *type)
+{
+  RETURN_NULL_IF_FAIL (type, NULL, NULL, "NULL type");
+  gcc::jit::recording::struct_ *struct_type = type->is_struct ();
+  return (gcc_jit_struct *)struct_type;
+}
+
+/* Public entrypoint.  See description in libgccjit.h.
+
+   After error-checking, the real work is done by the
+   gcc::jit::recording::vector_type::get_num_units method, in
+   jit-recording.c.  */
+
+size_t
+gcc_jit_vector_type_get_num_units (gcc_jit_vector_type *vector_type)
+{
+  RETURN_VAL_IF_FAIL (vector_type, 0, NULL, NULL, "NULL vector_type");
+  return vector_type->get_num_units ();
+}
+
+/* Public entrypoint.  See description in libgccjit.h.
+
+   After error-checking, the real work is done by the
+   gcc::jit::recording::vector_type::get_element_type method, in
+   jit-recording.c.  */
+
+gcc_jit_type *
+gcc_jit_vector_type_get_element_type (gcc_jit_vector_type *vector_type)
+{
+  RETURN_NULL_IF_FAIL (vector_type, NULL, NULL, "NULL vector_type");
+  return (gcc_jit_type *)vector_type->get_element_type ();
+}
+
+/* Public entrypoint.  See description in libgccjit.h.
+
+   After error-checking, the real work is done by the
+   gcc::jit::recording::type::unqualified method, in
+   jit-recording.c.  */
+
+gcc_jit_type *
+gcc_jit_type_unqualified (gcc_jit_type *type)
+{
+  RETURN_NULL_IF_FAIL (type, NULL, NULL, "NULL type");
+
+  return (gcc_jit_type *)type->unqualified ();
+}
+
+/* Public entrypoint.  See description in libgccjit.h.
+
+   After error-checking, the real work is done by the
+   gcc::jit::recording::type::dyn_cast_function_type method, in
+   jit-recording.c.  */
+
+gcc_jit_function_type *
+gcc_jit_type_dyncast_function_ptr_type (gcc_jit_type *type)
+{
+  RETURN_NULL_IF_FAIL (type, NULL, NULL, "NULL type");
+  gcc::jit::recording::type *func_ptr_type = type->dereference ();
+  RETURN_NULL_IF_FAIL (func_ptr_type, NULL, NULL, "NULL type");
+
+  return (gcc_jit_function_type *)func_ptr_type->dyn_cast_function_type ();
+}
+
+/* Public entrypoint.  See description in libgccjit.h.
+
+   After error-checking, the real work is done by the
+   gcc::jit::recording::function_type::get_return_type method, in
+   jit-recording.c.  */
+
+gcc_jit_type *
+gcc_jit_function_type_get_return_type (gcc_jit_function_type *function_type)
+{
+  RETURN_NULL_IF_FAIL (function_type, NULL, NULL, "NULL function_type");
+  return (gcc_jit_type *)function_type->get_return_type ();
+}
+
+/* Public entrypoint.  See description in libgccjit.h.
+
+   After error-checking, the real work is done by the
+   gcc::jit::recording::function_type::get_param_types method, in
+   jit-recording.c.  */
+
+size_t
+gcc_jit_function_type_get_param_count (gcc_jit_function_type *function_type)
+{
+  RETURN_VAL_IF_FAIL (function_type, 0, NULL, NULL, "NULL function_type");
+  return function_type->get_param_types ().length ();
+}
+
+/* Public entrypoint.  See description in libgccjit.h.
+
+   After error-checking, the real work is done by the
+   gcc::jit::recording::function_type::get_param_types method, in
+   jit-recording.c.  */
+
+gcc_jit_type *
+gcc_jit_function_type_get_param_type (gcc_jit_function_type *function_type,
+				size_t index)
+{
+  RETURN_NULL_IF_FAIL (function_type, NULL, NULL, "NULL function_type");
+  size_t num_params = function_type->get_param_types ().length ();
+  gcc::jit::recording::context *ctxt = function_type->m_ctxt;
+  RETURN_NULL_IF_FAIL_PRINTF3 (index < num_params,
+			       ctxt, NULL,
+			       "index of %ld is too large (%s has %ld params)",
+			       index,
+			       function_type->get_debug_string (),
+			       num_params);
+  return (gcc_jit_type *)function_type->get_param_types ()[index];
+}
+
 /* Public entrypoint.  See description in libgccjit.h.
 
    After error-checking, the real work is done by the
@@ -736,6 +932,42 @@ gcc_jit_struct_set_fields (gcc_jit_struct *struct_type,
 			   (gcc::jit::recording::field **)fields);
 }
 
+
+/* Public entrypoint.  See description in libgccjit.h.
+
+   After error-checking, the real work is done by the
+   gcc::jit::recording::fields::get_field method in
+   jit-recording.c.  */
+extern gcc_jit_field *
+gcc_jit_struct_get_field (gcc_jit_struct *struct_type,
+			   size_t index)
+{
+  RETURN_NULL_IF_FAIL (struct_type, NULL, NULL, "NULL struct type");
+  RETURN_NULL_IF_FAIL (struct_type->get_fields (), NULL, NULL,
+				"NULL struct fields");
+  size_t num_fields = struct_type->get_fields ()->length ();
+  RETURN_NULL_IF_FAIL_PRINTF3 (index < num_fields,
+			       NULL, NULL,
+			       "index of %ld is too large (%s has %ld fields)",
+			       index,
+			       struct_type->get_debug_string (),
+			       num_fields);
+  return (gcc_jit_field *)struct_type->get_fields ()->get_field (index);
+}
+
+/* Public entrypoint.  See description in libgccjit.h.
+
+   After error-checking, this calls the trivial
+   gcc::jit::recording::struct_::get_fields method in
+   jit-recording.h.  */
+
+size_t
+gcc_jit_struct_get_field_count (gcc_jit_struct *struct_type)
+{
+  RETURN_VAL_IF_FAIL (struct_type, 0, NULL, NULL, "NULL struct type");
+  return struct_type->get_fields ()->length ();
+}
+
 /* Public entrypoint.  See description in libgccjit.h.
 
    After error-checking, the real work is done by the
@@ -1017,6 +1249,35 @@ gcc_jit_function_get_param (gcc_jit_function *func, int index)
   return static_cast <gcc_jit_param *> (func->get_param (index));
 }
 
+/* Public entrypoint.  See description in libgccjit.h.
+
+   After error-checking, the real work is done by the
+   gcc::jit::recording::function::get_params method, in
+   jit-recording.h.
+  */
+
+size_t
+gcc_jit_function_get_param_count (gcc_jit_function *func)
+{
+  RETURN_VAL_IF_FAIL (func, 0, NULL, NULL, "NULL function");
+  gcc::jit::recording::context *ctxt = func->m_ctxt;
+  JIT_LOG_FUNC (ctxt->get_logger ());
+  return func->get_params ().length ();
+}
+
+/* Public entrypoint.  See description in libgccjit.h.
+
+   After error-checking, the real work is done by the
+   gcc::jit::recording::function::get_return_type method, in
+   jit-recording.h.  */
+
+gcc_jit_type *
+gcc_jit_function_get_return_type (gcc_jit_function *func)
+{
+    RETURN_NULL_IF_FAIL (func, NULL, NULL, "NULL function_type");
+    return (gcc_jit_type *)func->get_return_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 5c722c2c57f..a1c9436c545 100644
--- a/gcc/jit/libgccjit.h
+++ b/gcc/jit/libgccjit.h
@@ -61,6 +61,8 @@ typedef struct gcc_jit_result gcc_jit_result;
 	 +- gcc_jit_location
 	 +- gcc_jit_type
 	    +- gcc_jit_struct
+	    +- gcc_jit_function_type
+	    +- gcc_jit_vector_type
 	 +- gcc_jit_field
 	 +- gcc_jit_function
 	 +- gcc_jit_block
@@ -97,6 +99,12 @@ typedef struct gcc_jit_field gcc_jit_field;
    the layout for, or an opaque type.  */
 typedef struct gcc_jit_struct gcc_jit_struct;
 
+/* A gcc_jit_function_type encapsulates a function type.  */
+typedef struct gcc_jit_function_type gcc_jit_function_type;
+
+/* A gcc_jit_vector_type encapsulates a vector type.  */
+typedef struct gcc_jit_vector_type gcc_jit_vector_type;
+
 /* A gcc_jit_function encapsulates a function: either one that you're
    creating yourself, or a reference to one that you're dynamically
    linking to within the rest of the process.  */
@@ -654,6 +662,15 @@ gcc_jit_struct_set_fields (gcc_jit_struct *struct_type,
 			   int num_fields,
 			   gcc_jit_field **fields);
 
+/* Get a field by index.  */
+extern gcc_jit_field *
+gcc_jit_struct_get_field (gcc_jit_struct *struct_type,
+			   size_t index);
+
+/* Get the number of fields.  */
+extern size_t
+gcc_jit_struct_get_field_count (gcc_jit_struct *struct_type);
+
 /* Unions work similarly to structs.  */
 extern gcc_jit_type *
 gcc_jit_context_new_union_type (gcc_jit_context *ctxt,
@@ -1621,6 +1638,78 @@ gcc_jit_context_add_top_level_asm (gcc_jit_context *ctxt,
 				   gcc_jit_location *loc,
 				   const char *asm_stmts);
 
+#define LIBGCCJIT_HAVE_REFLECTION
+
+/* Reflection functions to get the number of parameters, return type of
+   a function and whether a type is a bool from the C API.
+
+   This API entrypoint was added in LIBGCCJIT_ABI_16; you can test for its
+   presence using
+     #ifdef LIBGCCJIT_HAVE_REFLECTION
+*/
+/* Get the return type of a function.  */
+extern gcc_jit_type *
+gcc_jit_function_get_return_type (gcc_jit_function *func);
+
+/* Get the number of params of a function.  */
+extern size_t
+gcc_jit_function_get_param_count (gcc_jit_function *func);
+
+/* Get the element type of an array type or NULL if it's not an array.  */
+extern gcc_jit_type *
+gcc_jit_type_dyncast_array (gcc_jit_type *type);
+
+/* Return non-zero if the type is a bool.  */
+extern int
+gcc_jit_type_is_bool (gcc_jit_type *type);
+
+/* Return the function type if it is one or NULL.  */
+extern gcc_jit_function_type *
+gcc_jit_type_dyncast_function_ptr_type (gcc_jit_type *type);
+
+/* Given a function type, return its return type.  */
+extern gcc_jit_type *
+gcc_jit_function_type_get_return_type (gcc_jit_function_type *function_type);
+
+/* Given a function type, return its number of parameters.  */
+extern size_t
+gcc_jit_function_type_get_param_count (gcc_jit_function_type *function_type);
+
+/* Given a function type, return the type of the specified parameter.  */
+extern gcc_jit_type *
+gcc_jit_function_type_get_param_type (gcc_jit_function_type *function_type,
+				size_t index);
+
+/* Return non-zero if the type is an integral.  */
+extern int
+gcc_jit_type_is_integral (gcc_jit_type *type);
+
+/* Return the type pointed by the pointer type or NULL if it's not a
+ * pointer.  */
+extern gcc_jit_type *
+gcc_jit_type_is_pointer (gcc_jit_type *type);
+
+/* Given a type, return a dynamic cast to a vector type or NULL.  */
+extern gcc_jit_vector_type *
+gcc_jit_type_dyncast_vector (gcc_jit_type *type);
+
+/* Given a type, return a dynamic cast to a struct type or NULL.  */
+extern gcc_jit_struct *
+gcc_jit_type_is_struct (gcc_jit_type *type);
+
+/* Given a vector type, return the number of units it contains.  */
+extern size_t
+gcc_jit_vector_type_get_num_units (gcc_jit_vector_type *vector_type);
+
+/* Given a vector type, return the type of its elements.  */
+extern gcc_jit_type *
+gcc_jit_vector_type_get_element_type (gcc_jit_vector_type *vector_type);
+
+/* Given a type, return the unqualified type, removing "const", "volatile"
+ * and alignment qualifiers.  */
+extern gcc_jit_type *
+gcc_jit_type_unqualified (gcc_jit_type *type);
+
 #ifdef __cplusplus
 }
 #endif /* __cplusplus */
diff --git a/gcc/jit/libgccjit.map b/gcc/jit/libgccjit.map
index 337ea6c7fe4..64e790949e8 100644
--- a/gcc/jit/libgccjit.map
+++ b/gcc/jit/libgccjit.map
@@ -205,3 +205,24 @@ LIBGCCJIT_ABI_15 {
     gcc_jit_extended_asm_add_clobber;
     gcc_jit_context_add_top_level_asm;
 } LIBGCCJIT_ABI_14;
+
+LIBGCCJIT_ABI_16 {
+  global:
+    gcc_jit_function_get_return_type;
+    gcc_jit_function_get_param_count;
+    gcc_jit_function_type_get_return_type;
+    gcc_jit_function_type_get_param_count;
+    gcc_jit_function_type_get_param_type;
+    gcc_jit_type_unqualified;
+    gcc_jit_type_dyncast_array;
+    gcc_jit_type_is_bool;
+    gcc_jit_type_dyncast_function_ptr_type;
+    gcc_jit_type_is_integral;
+    gcc_jit_type_is_pointer;
+    gcc_jit_type_dyncast_vector;
+    gcc_jit_vector_type_get_element_type;
+    gcc_jit_vector_type_get_num_units;
+    gcc_jit_struct_get_field;
+    gcc_jit_type_is_struct;
+    gcc_jit_struct_get_field_count;
+} LIBGCCJIT_ABI_15;
diff --git a/gcc/testsuite/jit.dg/all-non-failing-tests.h b/gcc/testsuite/jit.dg/all-non-failing-tests.h
index 84ef54a0386..a7fddf96db8 100644
--- a/gcc/testsuite/jit.dg/all-non-failing-tests.h
+++ b/gcc/testsuite/jit.dg/all-non-failing-tests.h
@@ -265,6 +265,13 @@
 #undef create_code
 #undef verify_code
 
+/* test-reflection.c */
+#define create_code create_code_reflection
+#define verify_code verify_code_reflection
+#include "test-reflection.c"
+#undef create_code
+#undef verify_code
+
 /* test-string-literal.c */
 #define create_code create_code_string_literal
 #define verify_code verify_code_string_literal
@@ -434,6 +441,9 @@ const struct testcase testcases[] = {
   {"reading_struct ",
    create_code_reading_struct ,
    verify_code_reading_struct },
+  {"reflection",
+   create_code_reflection ,
+   verify_code_reflection },
   {"string_literal",
    create_code_string_literal,
    verify_code_string_literal},
diff --git a/gcc/testsuite/jit.dg/test-reflection.c b/gcc/testsuite/jit.dg/test-reflection.c
new file mode 100644
index 00000000000..112a2455c07
--- /dev/null
+++ b/gcc/testsuite/jit.dg/test-reflection.c
@@ -0,0 +1,95 @@
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "libgccjit.h"
+
+#include "harness.h"
+
+void
+create_code (gcc_jit_context *ctxt, void *user_data)
+{
+  /* Do nothing.  */
+}
+
+void
+verify_code (gcc_jit_context *ctxt, gcc_jit_result *result)
+{
+  /* Get the built-in functions.  */
+  gcc_jit_function *builtin_sin =
+    gcc_jit_context_get_builtin_function (ctxt, "sin");
+
+  CHECK_VALUE (gcc_jit_function_get_param_count(builtin_sin), 1);
+
+  gcc_jit_type *double_type =
+    gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_DOUBLE);
+  CHECK_VALUE (gcc_jit_function_get_return_type(builtin_sin), double_type);
+  CHECK (!gcc_jit_type_is_integral(double_type));
+
+  gcc_jit_type *bool_type =
+    gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_BOOL);
+  CHECK (gcc_jit_type_is_bool(bool_type));
+  CHECK (!gcc_jit_type_is_integral(bool_type));
+
+  gcc_jit_type *aligned_bool_type =
+    gcc_jit_type_get_aligned(gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_BOOL), 8);
+  CHECK (gcc_jit_type_is_bool(aligned_bool_type));
+  CHECK (bool_type != aligned_bool_type);
+  CHECK_VALUE (gcc_jit_type_unqualified(aligned_bool_type), bool_type);
+
+  CHECK_VALUE (gcc_jit_type_unqualified(gcc_jit_type_get_const(bool_type)), bool_type);
+  CHECK_VALUE (gcc_jit_type_unqualified(gcc_jit_type_get_volatile(bool_type)), bool_type);
+
+  gcc_jit_type *int64 =
+    gcc_jit_context_get_int_type(ctxt, 8, 1);
+  CHECK (gcc_jit_type_is_integral(int64));
+  gcc_jit_type *uint64 =
+    gcc_jit_context_get_int_type(ctxt, 8, 0);
+  CHECK (gcc_jit_type_is_integral(uint64));
+  gcc_jit_type *int8 =
+    gcc_jit_context_get_int_type(ctxt, 1, 1);
+  CHECK (gcc_jit_type_is_integral(int8));
+  gcc_jit_type *uint8 =
+    gcc_jit_context_get_int_type(ctxt, 1, 0);
+  CHECK (gcc_jit_type_is_integral(uint8));
+
+  CHECK (!gcc_jit_type_dyncast_vector(double_type));
+  gcc_jit_type *vec_type = gcc_jit_type_get_vector (double_type, 4);
+  gcc_jit_vector_type *vector_type = gcc_jit_type_dyncast_vector(vec_type);
+  CHECK (vector_type);
+  CHECK (vec_type != double_type);
+  CHECK_VALUE (gcc_jit_vector_type_get_element_type(vector_type), double_type);
+  CHECK_VALUE (gcc_jit_vector_type_get_num_units(vector_type), 4);
+
+  CHECK (!gcc_jit_type_is_pointer(double_type));
+  CHECK_VALUE (gcc_jit_type_is_pointer(gcc_jit_type_get_pointer(double_type)), double_type);
+
+  gcc_jit_type* params[2] = {int8, uint64};
+  gcc_jit_type *function_ptr_type = gcc_jit_context_new_function_ptr_type(ctxt, NULL, int64, 2, params, 0);
+  CHECK (!gcc_jit_type_dyncast_function_ptr_type (int64));
+  gcc_jit_function_type *function_type = gcc_jit_type_dyncast_function_ptr_type (function_ptr_type);
+  CHECK (function_type);
+  int param_count = gcc_jit_function_type_get_param_count(function_type);
+  CHECK_VALUE (param_count, 2);
+  gcc_jit_type *return_type = gcc_jit_function_type_get_return_type(function_type);
+  CHECK_VALUE (return_type, int64);
+  gcc_jit_type *param1 = gcc_jit_function_type_get_param_type(function_type, 0);
+  CHECK_VALUE (param1, int8);
+  gcc_jit_type *param2 = gcc_jit_function_type_get_param_type(function_type, 1);
+  CHECK_VALUE (param2, uint64);
+
+  gcc_jit_field *field1 = gcc_jit_context_new_field (ctxt, NULL, uint64, "field1");
+  gcc_jit_field *field2 = gcc_jit_context_new_field (ctxt, NULL, double_type, "field2");
+  gcc_jit_field *fields[2] = { field1, field2 };
+  gcc_jit_struct *struct_type = gcc_jit_context_new_struct_type (ctxt, NULL, "testStruct", 2, fields);
+  CHECK_VALUE (gcc_jit_struct_get_field_count(struct_type), 2);
+  CHECK_VALUE (gcc_jit_struct_get_field(struct_type, 0), field1);
+  CHECK_VALUE (gcc_jit_struct_get_field(struct_type, 1), field2);
+  CHECK (!gcc_jit_type_is_struct(double_type));
+  gcc_jit_struct *struct_ty = gcc_jit_type_is_struct(gcc_jit_struct_as_type(struct_type));
+  CHECK_VALUE (struct_ty, struct_type);
+
+  CHECK (!gcc_jit_type_dyncast_array(double_type));
+  gcc_jit_type* array_type = gcc_jit_context_new_array_type(ctxt, NULL, double_type, 1);
+  CHECK_VALUE (gcc_jit_type_dyncast_array(array_type), double_type);
+}
+
-- 
2.32.0


^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re: [PATCH] libgccjit: add some reflection functions in the jit C api
  2021-07-19 16:10                                     ` Antoni Boucher
@ 2021-07-29 12:59                                       ` Antoni Boucher
  2021-08-31 12:34                                         ` Antoni Boucher
  0 siblings, 1 reply; 35+ messages in thread
From: Antoni Boucher @ 2021-07-29 12:59 UTC (permalink / raw)
  To: David Malcolm; +Cc: Antoni Boucher via Jit, gcc-patches

David: PING

Le lundi 19 juillet 2021 à 12:10 -0400, Antoni Boucher a écrit :
> I'm sending the patch once again for review/approval.
> 
> I fixed the doc to use the new function names.
> 
> Le vendredi 18 juin 2021 à 16:37 -0400, David Malcolm a écrit :
> > On Fri, 2021-06-18 at 15:41 -0400, Antoni Boucher wrote:
> > > I have write access now.
> > 
> > Great.
> > 
> > > I'm not sure how I'm supposed to send my patches:
> > > should I put it in personal branches and you'll merge them?
> > 
> > Please send them to this mailing list for review; once they're
> > approved
> > you can merge them.
> > 
> > > 
> > > And for the MAINTAINERS file, should I just push to master right
> > > away,
> > > after sending it to the mailing list?
> > 
> > I think people just push the MAINTAINERS change and then let the
> > list
> > know, since it makes a good test that write access is working
> > correctly.
> > 
> > Dave
> > 
> > > 
> > > Thanks for your help!
> > > 
> > > Le vendredi 18 juin 2021 à 12:09 -0400, David Malcolm a écrit :
> > > > On Fri, 2021-06-18 at 11:55 -0400, Antoni Boucher wrote:
> > > > > Le vendredi 11 juin 2021 à 14:00 -0400, David Malcolm a
> > > > > écrit :
> > > > > > On Fri, 2021-06-11 at 08:15 -0400, Antoni Boucher wrote:
> > > > > > > Thank you for your answer.
> > > > > > > I attached the updated patch.
> > > > > > 
> > > > > > BTW you (or possibly me) dropped the mailing lists; was
> > > > > > that
> > > > > > deliberate?
> > > > > 
> > > > > Oh, my bad.
> > > > > 
> > > > 
> > > > [...]
> > > > 
> > > > 
> > > > > > 
> > > > > > 
> > > > > > > I have signed the FSF copyright attribution.
> > > > > > 
> > > > > > I can push changes on your behalf, but I'd prefer it if you
> > > > > > did
> > > > > > it,
> > > > > > especially given that you have various other patches you
> > > > > > want
> > > > > > to
> > > > > > get
> > > > > > in.
> > > > > > 
> > > > > > Instructions on how to get push rights to the git repo are
> > > > > > here:
> > > > > >   https://gcc.gnu.org/gitwrite.html
> > > > > > 
> > > > > > I can sponsor you.
> > > > > 
> > > > > Thanks.
> > > > > I did sign up to get push rights.
> > > > > Have you accepted my request to get those?
> > > > 
> > > > I did, but I didn't see any kind of notification.  Did you get
> > > > an
> > > > email
> > > > about it?
> > > > 
> > > > 
> > > > Dave
> > > > 
> > > 
> > > 
> > 
> > 
> 



^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re: [PATCH] libgccjit: add some reflection functions in the jit C api
  2021-07-29 12:59                                       ` Antoni Boucher
@ 2021-08-31 12:34                                         ` Antoni Boucher
  0 siblings, 0 replies; 35+ messages in thread
From: Antoni Boucher @ 2021-08-31 12:34 UTC (permalink / raw)
  To: David Malcolm; +Cc: Antoni Boucher via Jit, gcc-patches

David: PING

Le jeudi 29 juillet 2021 à 08:59 -0400, Antoni Boucher a écrit :
> David: PING
> 
> Le lundi 19 juillet 2021 à 12:10 -0400, Antoni Boucher a écrit :
> > I'm sending the patch once again for review/approval.
> > 
> > I fixed the doc to use the new function names.
> > 
> > Le vendredi 18 juin 2021 à 16:37 -0400, David Malcolm a écrit :
> > > On Fri, 2021-06-18 at 15:41 -0400, Antoni Boucher wrote:
> > > > I have write access now.
> > > 
> > > Great.
> > > 
> > > > I'm not sure how I'm supposed to send my patches:
> > > > should I put it in personal branches and you'll merge them?
> > > 
> > > Please send them to this mailing list for review; once they're
> > > approved
> > > you can merge them.
> > > 
> > > > 
> > > > And for the MAINTAINERS file, should I just push to master
> > > > right
> > > > away,
> > > > after sending it to the mailing list?
> > > 
> > > I think people just push the MAINTAINERS change and then let the
> > > list
> > > know, since it makes a good test that write access is working
> > > correctly.
> > > 
> > > Dave
> > > 
> > > > 
> > > > Thanks for your help!
> > > > 
> > > > Le vendredi 18 juin 2021 à 12:09 -0400, David Malcolm a écrit :
> > > > > On Fri, 2021-06-18 at 11:55 -0400, Antoni Boucher wrote:
> > > > > > Le vendredi 11 juin 2021 à 14:00 -0400, David Malcolm a
> > > > > > écrit :
> > > > > > > On Fri, 2021-06-11 at 08:15 -0400, Antoni Boucher wrote:
> > > > > > > > Thank you for your answer.
> > > > > > > > I attached the updated patch.
> > > > > > > 
> > > > > > > BTW you (or possibly me) dropped the mailing lists; was
> > > > > > > that
> > > > > > > deliberate?
> > > > > > 
> > > > > > Oh, my bad.
> > > > > > 
> > > > > 
> > > > > [...]
> > > > > 
> > > > > 
> > > > > > > 
> > > > > > > 
> > > > > > > > I have signed the FSF copyright attribution.
> > > > > > > 
> > > > > > > I can push changes on your behalf, but I'd prefer it if
> > > > > > > you
> > > > > > > did
> > > > > > > it,
> > > > > > > especially given that you have various other patches you
> > > > > > > want
> > > > > > > to
> > > > > > > get
> > > > > > > in.
> > > > > > > 
> > > > > > > Instructions on how to get push rights to the git repo
> > > > > > > are
> > > > > > > here:
> > > > > > >   https://gcc.gnu.org/gitwrite.html
> > > > > > > 
> > > > > > > I can sponsor you.
> > > > > > 
> > > > > > Thanks.
> > > > > > I did sign up to get push rights.
> > > > > > Have you accepted my request to get those?
> > > > > 
> > > > > I did, but I didn't see any kind of notification.  Did you
> > > > > get
> > > > > an
> > > > > email
> > > > > about it?
> > > > > 
> > > > > 
> > > > > Dave
> > > > > 
> > > > 
> > > > 
> > > 
> > > 
> > 
> 
> 



^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re: [PATCH] libgccjit: add some reflection functions in the jit C api
  2021-06-18 20:37                                   ` David Malcolm
  2021-07-19 16:10                                     ` Antoni Boucher
@ 2021-09-28  0:53                                     ` Antoni Boucher
  2021-10-13  2:09                                       ` Antoni Boucher
  2021-11-20  0:53                                       ` David Malcolm
  1 sibling, 2 replies; 35+ messages in thread
From: Antoni Boucher @ 2021-09-28  0:53 UTC (permalink / raw)
  To: David Malcolm; +Cc: Antoni Boucher via Jit, gcc-patches

[-- Attachment #1: Type: text/plain, Size: 2276 bytes --]

I fixed an issue (it would show an error message when
gcc_jit_type_dyncast_function_ptr_type was called on a type different
than a function pointer type).

Here's the updated patch.

Le vendredi 18 juin 2021 à 16:37 -0400, David Malcolm a écrit :
> On Fri, 2021-06-18 at 15:41 -0400, Antoni Boucher wrote:
> > I have write access now.
> 
> Great.
> 
> > I'm not sure how I'm supposed to send my patches:
> > should I put it in personal branches and you'll merge them?
> 
> Please send them to this mailing list for review; once they're
> approved
> you can merge them.
> 
> > 
> > And for the MAINTAINERS file, should I just push to master right
> > away,
> > after sending it to the mailing list?
> 
> I think people just push the MAINTAINERS change and then let the list
> know, since it makes a good test that write access is working
> correctly.
> 
> Dave
> 
> > 
> > Thanks for your help!
> > 
> > Le vendredi 18 juin 2021 à 12:09 -0400, David Malcolm a écrit :
> > > On Fri, 2021-06-18 at 11:55 -0400, Antoni Boucher wrote:
> > > > Le vendredi 11 juin 2021 à 14:00 -0400, David Malcolm a écrit :
> > > > > On Fri, 2021-06-11 at 08:15 -0400, Antoni Boucher wrote:
> > > > > > Thank you for your answer.
> > > > > > I attached the updated patch.
> > > > > 
> > > > > BTW you (or possibly me) dropped the mailing lists; was that
> > > > > deliberate?
> > > > 
> > > > Oh, my bad.
> > > > 
> > > 
> > > [...]
> > > 
> > > 
> > > > > 
> > > > > 
> > > > > > I have signed the FSF copyright attribution.
> > > > > 
> > > > > I can push changes on your behalf, but I'd prefer it if you
> > > > > did
> > > > > it,
> > > > > especially given that you have various other patches you want
> > > > > to
> > > > > get
> > > > > in.
> > > > > 
> > > > > Instructions on how to get push rights to the git repo are
> > > > > here:
> > > > >   https://gcc.gnu.org/gitwrite.html
> > > > > 
> > > > > I can sponsor you.
> > > > 
> > > > Thanks.
> > > > I did sign up to get push rights.
> > > > Have you accepted my request to get those?
> > > 
> > > I did, but I didn't see any kind of notification.  Did you get an
> > > email
> > > about it?
> > > 
> > > 
> > > Dave
> > > 
> > 
> > 
> 
> 


[-- Attachment #2: 0001-libgccjit-Add-some-reflection-functions-PR96889.patch --]
[-- Type: text/x-patch, Size: 30865 bytes --]

From 95f8b85bcc7b1259eef1e9916de824c752b2f2c0 Mon Sep 17 00:00:00 2001
From: Antoni Boucher <bouanto@zoho.com>
Date: Sat, 1 Aug 2020 17:52:17 -0400
Subject: [PATCH] libgccjit: Add some reflection functions [PR96889]

2021-07-19  Antoni Boucher  <bouanto@zoho.com>

gcc/jit/
	PR target/96889
	* docs/topics/compatibility.rst (LIBGCCJIT_ABI_16): New ABI tag.
	* docs/topics/functions.rst: Add documentation for the
	functions gcc_jit_function_get_return_type and
	gcc_jit_function_get_param_count
	* docs/topics/types.rst: Add documentation for the functions
	gcc_jit_function_type_get_return_type,
	gcc_jit_function_type_get_param_count,
	gcc_jit_function_type_get_param_type,
	gcc_jit_type_unqualified, gcc_jit_type_dyncast_array,
	gcc_jit_type_is_bool,
	gcc_jit_type_dyncast_function_ptr_type,
	gcc_jit_type_is_integral, gcc_jit_type_is_pointer,
	gcc_jit_type_dyncast_vector,
	gcc_jit_vector_type_get_element_type,
	gcc_jit_vector_type_get_num_units,
	gcc_jit_struct_get_field, gcc_jit_type_is_struct,
	and gcc_jit_struct_get_field_count
	* libgccjit.c:
	(gcc_jit_function_get_return_type, gcc_jit_function_get_param_count,
	gcc_jit_function_type_get_return_type,
	gcc_jit_function_type_get_param_count,
	gcc_jit_function_type_get_param_type, gcc_jit_type_unqualified,
	gcc_jit_type_dyncast_array, gcc_jit_type_is_bool,
	gcc_jit_type_dyncast_function_ptr_type, gcc_jit_type_is_integral,
	gcc_jit_type_is_pointer, gcc_jit_type_dyncast_vector,
	gcc_jit_vector_type_get_element_type,
	gcc_jit_vector_type_get_num_units, gcc_jit_struct_get_field,
	gcc_jit_type_is_struct, gcc_jit_struct_get_field_count): New
	functions.
	(struct gcc_jit_function_type, struct gcc_jit_vector_type):
	New types.
	* libgccjit.h:
	(gcc_jit_function_get_return_type, gcc_jit_function_get_param_count,
	gcc_jit_function_type_get_return_type,
	gcc_jit_function_type_get_param_count,
	gcc_jit_function_type_get_param_type, gcc_jit_type_unqualified,
	gcc_jit_type_dyncast_array, gcc_jit_type_is_bool,
	gcc_jit_type_dyncast_function_ptr_type, gcc_jit_type_is_integral,
	gcc_jit_type_is_pointer, gcc_jit_type_dyncast_vector,
	gcc_jit_vector_type_get_element_type,
	gcc_jit_vector_type_get_num_units, gcc_jit_struct_get_field,
	gcc_jit_type_is_struct, gcc_jit_struct_get_field_count): New
	function declarations.
	(struct gcc_jit_function_type, struct gcc_jit_vector_type):
	New types.
	* jit-recording.h: New functions (is_struct and is_vector)
	* libgccjit.map (LIBGCCJIT_ABI_16): New ABI tag.

gcc/testsuite/
	PR target/96889
	* jit.dg/all-non-failing-tests.h: Add test-reflection.c.
	* jit.dg/test-reflection.c: New test.
---
 gcc/jit/docs/topics/compatibility.rst        |  43 ++-
 gcc/jit/docs/topics/functions.rst            |  26 ++
 gcc/jit/docs/topics/types.rst                | 122 +++++++++
 gcc/jit/jit-recording.h                      |   7 +
 gcc/jit/libgccjit.c                          | 264 +++++++++++++++++++
 gcc/jit/libgccjit.h                          |  89 +++++++
 gcc/jit/libgccjit.map                        |  21 ++
 gcc/testsuite/jit.dg/all-non-failing-tests.h |  10 +
 gcc/testsuite/jit.dg/test-reflection.c       |  95 +++++++
 9 files changed, 676 insertions(+), 1 deletion(-)
 create mode 100644 gcc/testsuite/jit.dg/test-reflection.c

diff --git a/gcc/jit/docs/topics/compatibility.rst b/gcc/jit/docs/topics/compatibility.rst
index 239b6aa1a92..52ee3f860a7 100644
--- a/gcc/jit/docs/topics/compatibility.rst
+++ b/gcc/jit/docs/topics/compatibility.rst
@@ -230,7 +230,7 @@ entrypoints:
 .. _LIBGCCJIT_ABI_15:
 
 ``LIBGCCJIT_ABI_15``
------------------------
+--------------------
 ``LIBGCCJIT_ABI_15`` covers the addition of API entrypoints for directly
 embedding assembler instructions:
 
@@ -243,3 +243,44 @@ embedding assembler instructions:
   * :func:`gcc_jit_extended_asm_add_input_operand`
   * :func:`gcc_jit_extended_asm_add_clobber`
   * :func:`gcc_jit_context_add_top_level_asm`
+
+.. _LIBGCCJIT_ABI_16:
+
+``LIBGCCJIT_ABI_16``
+--------------------
+``LIBGCCJIT_ABI_16`` covers the addition of reflection functions via API
+entrypoints:
+
+  * :func:`gcc_jit_function_get_return_type`
+
+  * :func:`gcc_jit_function_get_param_count`
+
+  * :func:`gcc_jit_type_dyncast_array`
+
+  * :func:`gcc_jit_type_is_bool`
+
+  * :func:`gcc_jit_type_is_integral`
+
+  * :func:`gcc_jit_type_is_pointer`
+
+  * :func:`gcc_jit_type_is_struct`
+
+  * :func:`gcc_jit_type_dyncast_vector`
+
+  * :func:`gcc_jit_type_unqualified`
+
+  * :func:`gcc_jit_type_dyncast_function_ptr_type`
+
+  * :func:`gcc_jit_function_type_get_return_type`
+
+  * :func:`gcc_jit_function_type_get_param_count`
+
+  * :func:`gcc_jit_function_type_get_param_type`
+
+  * :func:`gcc_jit_vector_type_get_num_units`
+
+  * :func:`gcc_jit_vector_type_get_element_type`
+
+  * :func:`gcc_jit_struct_get_field`
+
+  * :func:`gcc_jit_struct_get_field_count`
diff --git a/gcc/jit/docs/topics/functions.rst b/gcc/jit/docs/topics/functions.rst
index b2d9239aa0a..839934588da 100644
--- a/gcc/jit/docs/topics/functions.rst
+++ b/gcc/jit/docs/topics/functions.rst
@@ -171,6 +171,32 @@ Functions
    underlying string, so it is valid to pass in a pointer to an on-stack
    buffer.
 
+.. function::  size_t \
+               gcc_jit_function_get_param_count (gcc_jit_function *func)
+
+   Get the number of parameters of the function.
+
+.. function::  gcc_jit_type *\
+               gcc_jit_function_get_return_type (gcc_jit_function *func)
+
+   Get the return type of the function.
+
+   The API entrypoints relating to getting info about parameters and return
+   types:
+
+      * :c:func:`gcc_jit_function_get_return_type`
+
+      * :c:func:`gcc_jit_function_get_param_count`
+
+   were added in :ref:`LIBGCCJIT_ABI_16`; you can test for their presence
+   using
+
+   .. code-block:: c
+
+      #ifdef LIBGCCJIT_HAVE_REFLECTION
+
+   .. type:: gcc_jit_case
+
 Blocks
 ------
 .. type:: gcc_jit_block
diff --git a/gcc/jit/docs/topics/types.rst b/gcc/jit/docs/topics/types.rst
index 831f11b679a..6260e9afba4 100644
--- a/gcc/jit/docs/topics/types.rst
+++ b/gcc/jit/docs/topics/types.rst
@@ -345,3 +345,125 @@ Function pointer types
 
 Function pointer types can be created using
 :c:func:`gcc_jit_context_new_function_ptr_type`.
+
+Reflection API
+--------------
+
+.. function::  gcc_jit_type *\
+               gcc_jit_type_dyncast_array (gcc_jit_type *type)
+
+     Get the element type of an array type or NULL if it's not an array.
+
+.. function::  int\
+               gcc_jit_type_is_bool (gcc_jit_type *type)
+
+     Return non-zero if the type is a bool.
+
+.. function::  gcc_jit_function_type *\
+               gcc_jit_type_dyncast_function_ptr_type (gcc_jit_type *type)
+
+     Return the function type if it is one or NULL.
+
+.. function::  gcc_jit_type *\
+               gcc_jit_function_type_get_return_type (gcc_jit_function_type *function_type)
+
+     Given a function type, return its return type.
+
+.. function::  size_t\
+               gcc_jit_function_type_get_param_count (gcc_jit_function_type *function_type)
+
+     Given a function type, return its number of parameters.
+
+.. function::  gcc_jit_type *\
+               gcc_jit_function_type_get_param_type (gcc_jit_function_type *function_type,
+                                                     size_t index)
+
+     Given a function type, return the type of the specified parameter.
+
+.. function::  int\
+               gcc_jit_type_is_integral (gcc_jit_type *type)
+
+     Return non-zero if the type is an integral.
+
+.. function::  gcc_jit_type *\
+               gcc_jit_type_is_pointer (gcc_jit_type *type)
+
+     Return the type pointed by the pointer type or NULL if it's not a pointer.
+
+.. function::  gcc_jit_vector_type *\
+               gcc_jit_type_dyncast_vector (gcc_jit_type *type)
+
+     Given a type, return a dynamic cast to a vector type or NULL.
+
+.. function::  gcc_jit_struct *\
+               gcc_jit_type_is_struct (gcc_jit_type *type)
+
+     Given a type, return a dynamic cast to a struct type or NULL.
+
+.. function::  size_t\
+               gcc_jit_vector_type_get_num_units (gcc_jit_vector_type *vector_type)
+
+     Given a vector type, return the number of units it contains.
+
+.. function::  gcc_jit_type *\
+               gcc_jit_vector_type_get_element_type (gcc_jit_vector_type * vector_type)
+
+     Given a vector type, return the type of its elements.
+
+.. function::  gcc_jit_type *\
+               gcc_jit_type_unqualified (gcc_jit_type *type)
+
+     Given a type, return the unqualified type, removing "const", "volatile" and
+     alignment qualifiers.
+
+.. function::  gcc_jit_field *\
+               gcc_jit_struct_get_field (gcc_jit_struct *struct_type,
+                                         size_t index)
+
+     Get a struct field by index.
+
+.. function::  size_t\
+               gcc_jit_struct_get_field_count (gcc_jit_struct *struct_type)
+
+     Get the number of fields in the struct.
+
+   The API entrypoints related to the reflection API:
+
+      * :c:func:`gcc_jit_function_type_get_return_type`
+
+      * :c:func:`gcc_jit_function_type_get_param_count`
+
+      * :c:func:`gcc_jit_function_type_get_param_type`
+
+      * :c:func:`gcc_jit_type_unqualified`
+
+      * :c:func:`gcc_jit_type_dyncast_array`
+
+      * :c:func:`gcc_jit_type_is_bool`
+
+      * :c:func:`gcc_jit_type_dyncast_function_ptr_type`
+
+      * :c:func:`gcc_jit_type_is_integral`
+
+      * :c:func:`gcc_jit_type_is_pointer`
+
+      * :c:func:`gcc_jit_type_dyncast_vector`
+
+      * :c:func:`gcc_jit_vector_type_get_element_type`
+
+      * :c:func:`gcc_jit_vector_type_get_num_units`
+
+      * :c:func:`gcc_jit_struct_get_field`
+
+      * :c:func:`gcc_jit_type_is_struct`
+
+      * :c:func:`gcc_jit_struct_get_field_count`
+
+   were added in :ref:`LIBGCCJIT_ABI_16`; you can test for their presence
+   using
+
+   .. code-block:: c
+
+      #ifdef LIBGCCJIT_HAVE_REFLECTION
+
+   .. type:: gcc_jit_case
diff --git a/gcc/jit/jit-recording.h b/gcc/jit/jit-recording.h
index 03fa1160cf0..4a994fe7094 100644
--- a/gcc/jit/jit-recording.h
+++ b/gcc/jit/jit-recording.h
@@ -546,7 +546,9 @@ public:
   virtual bool is_bool () const = 0;
   virtual type *is_pointer () = 0;
   virtual type *is_array () = 0;
+  virtual struct_ *is_struct () { return NULL; }
   virtual bool is_void () const { return false; }
+  virtual vector_type *is_vector () { return NULL; }
   virtual bool has_known_size () const { return true; }
 
   bool is_numeric () const
@@ -663,6 +665,7 @@ public:
   bool is_bool () const FINAL OVERRIDE { return m_other_type->is_bool (); }
   type *is_pointer () FINAL OVERRIDE { return m_other_type->is_pointer (); }
   type *is_array () FINAL OVERRIDE { return m_other_type->is_array (); }
+  struct_ *is_struct () FINAL OVERRIDE { return m_other_type->is_struct (); }
 
 protected:
   type *m_other_type;
@@ -745,6 +748,8 @@ public:
 
   void replay_into (replayer *) FINAL OVERRIDE;
 
+  vector_type *is_vector () FINAL OVERRIDE { return this; }
+
 private:
   string * make_debug_string () FINAL OVERRIDE;
   void write_reproducer (reproducer &r) FINAL OVERRIDE;
@@ -951,6 +956,8 @@ public:
 
   const char *access_as_type (reproducer &r) FINAL OVERRIDE;
 
+  struct_ *is_struct () FINAL OVERRIDE { return this; }
+
 private:
   string * make_debug_string () FINAL OVERRIDE;
   void write_reproducer (reproducer &r) FINAL OVERRIDE;
diff --git a/gcc/jit/libgccjit.c b/gcc/jit/libgccjit.c
index 7fa948007ad..c744b634f4b 100644
--- a/gcc/jit/libgccjit.c
+++ b/gcc/jit/libgccjit.c
@@ -60,6 +60,14 @@ struct gcc_jit_struct : public gcc::jit::recording::struct_
 {
 };
 
+struct gcc_jit_function_type : public gcc::jit::recording::function_type
+{
+};
+
+struct gcc_jit_vector_type : public gcc::jit::recording::vector_type
+{
+};
+
 struct gcc_jit_field : public gcc::jit::recording::field
 {
 };
@@ -515,6 +523,197 @@ gcc_jit_type_get_volatile (gcc_jit_type *type)
   return (gcc_jit_type *)type->get_volatile ();
 }
 
+/* Public entrypoint.  See description in libgccjit.h.
+
+   After error-checking, the real work is done by the
+   gcc::jit::recording::type::is_array method, in
+   jit-recording.c.  */
+
+gcc_jit_type *
+gcc_jit_type_dyncast_array (gcc_jit_type *type)
+{
+  RETURN_NULL_IF_FAIL (type, NULL, NULL, "NULL type");
+
+  return (gcc_jit_type *)type->is_array ();
+}
+
+/* Public entrypoint.  See description in libgccjit.h.
+
+   After error-checking, the real work is done by the
+   gcc::jit::recording::type::is_bool method, in
+   jit-recording.c.  */
+
+int
+gcc_jit_type_is_bool (gcc_jit_type *type)
+{
+  RETURN_VAL_IF_FAIL (type, FALSE, NULL, NULL, "NULL type");
+
+  return type->is_bool ();
+}
+
+/* Public entrypoint.  See description in libgccjit.h.
+
+   After error-checking, the real work is done by the
+   gcc::jit::recording::type::is_pointer method, in
+   jit-recording.c.  */
+
+gcc_jit_type *
+gcc_jit_type_is_pointer (gcc_jit_type *type)
+{
+  RETURN_NULL_IF_FAIL (type, NULL, NULL, "NULL type");
+
+  return (gcc_jit_type *)type->is_pointer ();
+}
+
+/* Public entrypoint.  See description in libgccjit.h.
+
+   After error-checking, the real work is done by the
+   gcc::jit::recording::type::is_int method, in
+   jit-recording.c.  */
+
+int
+gcc_jit_type_is_integral (gcc_jit_type *type)
+{
+  RETURN_VAL_IF_FAIL (type, FALSE, NULL, NULL, "NULL type");
+
+  return type->is_int ();
+}
+
+/* Public entrypoint.  See description in libgccjit.h.
+
+   After error-checking, the real work is done by the
+   gcc::jit::recording::type::is_vector method, in
+   jit-recording.c.  */
+
+gcc_jit_vector_type *
+gcc_jit_type_dyncast_vector (gcc_jit_type *type)
+{
+  RETURN_NULL_IF_FAIL (type, NULL, NULL, "NULL type");
+  gcc::jit::recording::vector_type *vector_type = type->is_vector ();
+  return (gcc_jit_vector_type *)vector_type;
+}
+
+/* Public entrypoint.  See description in libgccjit.h.
+
+   After error-checking, the real work is done by the
+   gcc::jit::recording::type::is_struct method, in
+   jit-recording.c.  */
+
+gcc_jit_struct *
+gcc_jit_type_is_struct (gcc_jit_type *type)
+{
+  RETURN_NULL_IF_FAIL (type, NULL, NULL, "NULL type");
+  gcc::jit::recording::struct_ *struct_type = type->is_struct ();
+  return (gcc_jit_struct *)struct_type;
+}
+
+/* Public entrypoint.  See description in libgccjit.h.
+
+   After error-checking, the real work is done by the
+   gcc::jit::recording::vector_type::get_num_units method, in
+   jit-recording.c.  */
+
+size_t
+gcc_jit_vector_type_get_num_units (gcc_jit_vector_type *vector_type)
+{
+  RETURN_VAL_IF_FAIL (vector_type, 0, NULL, NULL, "NULL vector_type");
+  return vector_type->get_num_units ();
+}
+
+/* Public entrypoint.  See description in libgccjit.h.
+
+   After error-checking, the real work is done by the
+   gcc::jit::recording::vector_type::get_element_type method, in
+   jit-recording.c.  */
+
+gcc_jit_type *
+gcc_jit_vector_type_get_element_type (gcc_jit_vector_type *vector_type)
+{
+  RETURN_NULL_IF_FAIL (vector_type, NULL, NULL, "NULL vector_type");
+  return (gcc_jit_type *)vector_type->get_element_type ();
+}
+
+/* Public entrypoint.  See description in libgccjit.h.
+
+   After error-checking, the real work is done by the
+   gcc::jit::recording::type::unqualified method, in
+   jit-recording.c.  */
+
+gcc_jit_type *
+gcc_jit_type_unqualified (gcc_jit_type *type)
+{
+  RETURN_NULL_IF_FAIL (type, NULL, NULL, "NULL type");
+
+  return (gcc_jit_type *)type->unqualified ();
+}
+
+/* Public entrypoint.  See description in libgccjit.h.
+
+   After error-checking, the real work is done by the
+   gcc::jit::recording::type::dyn_cast_function_type method, in
+   jit-recording.c.  */
+
+gcc_jit_function_type *
+gcc_jit_type_dyncast_function_ptr_type (gcc_jit_type *type)
+{
+  RETURN_NULL_IF_FAIL (type, NULL, NULL, "NULL type");
+  gcc::jit::recording::type *func_ptr_type = type->dereference ();
+  if (!func_ptr_type)
+  {
+    return NULL;
+  }
+
+  return (gcc_jit_function_type *)func_ptr_type->dyn_cast_function_type ();
+}
+
+/* Public entrypoint.  See description in libgccjit.h.
+
+   After error-checking, the real work is done by the
+   gcc::jit::recording::function_type::get_return_type method, in
+   jit-recording.c.  */
+
+gcc_jit_type *
+gcc_jit_function_type_get_return_type (gcc_jit_function_type *function_type)
+{
+  RETURN_NULL_IF_FAIL (function_type, NULL, NULL, "NULL function_type");
+  return (gcc_jit_type *)function_type->get_return_type ();
+}
+
+/* Public entrypoint.  See description in libgccjit.h.
+
+   After error-checking, the real work is done by the
+   gcc::jit::recording::function_type::get_param_types method, in
+   jit-recording.c.  */
+
+size_t
+gcc_jit_function_type_get_param_count (gcc_jit_function_type *function_type)
+{
+  RETURN_VAL_IF_FAIL (function_type, 0, NULL, NULL, "NULL function_type");
+  return function_type->get_param_types ().length ();
+}
+
+/* Public entrypoint.  See description in libgccjit.h.
+
+   After error-checking, the real work is done by the
+   gcc::jit::recording::function_type::get_param_types method, in
+   jit-recording.c.  */
+
+gcc_jit_type *
+gcc_jit_function_type_get_param_type (gcc_jit_function_type *function_type,
+				size_t index)
+{
+  RETURN_NULL_IF_FAIL (function_type, NULL, NULL, "NULL function_type");
+  size_t num_params = function_type->get_param_types ().length ();
+  gcc::jit::recording::context *ctxt = function_type->m_ctxt;
+  RETURN_NULL_IF_FAIL_PRINTF3 (index < num_params,
+			       ctxt, NULL,
+			       "index of %ld is too large (%s has %ld params)",
+			       index,
+			       function_type->get_debug_string (),
+			       num_params);
+  return (gcc_jit_type *)function_type->get_param_types ()[index];
+}
+
 /* Public entrypoint.  See description in libgccjit.h.
 
    After error-checking, the real work is done by the
@@ -736,6 +935,42 @@ gcc_jit_struct_set_fields (gcc_jit_struct *struct_type,
 			   (gcc::jit::recording::field **)fields);
 }
 
+
+/* Public entrypoint.  See description in libgccjit.h.
+
+   After error-checking, the real work is done by the
+   gcc::jit::recording::fields::get_field method in
+   jit-recording.c.  */
+extern gcc_jit_field *
+gcc_jit_struct_get_field (gcc_jit_struct *struct_type,
+			   size_t index)
+{
+  RETURN_NULL_IF_FAIL (struct_type, NULL, NULL, "NULL struct type");
+  RETURN_NULL_IF_FAIL (struct_type->get_fields (), NULL, NULL,
+				"NULL struct fields");
+  size_t num_fields = struct_type->get_fields ()->length ();
+  RETURN_NULL_IF_FAIL_PRINTF3 (index < num_fields,
+			       NULL, NULL,
+			       "index of %ld is too large (%s has %ld fields)",
+			       index,
+			       struct_type->get_debug_string (),
+			       num_fields);
+  return (gcc_jit_field *)struct_type->get_fields ()->get_field (index);
+}
+
+/* Public entrypoint.  See description in libgccjit.h.
+
+   After error-checking, this calls the trivial
+   gcc::jit::recording::struct_::get_fields method in
+   jit-recording.h.  */
+
+size_t
+gcc_jit_struct_get_field_count (gcc_jit_struct *struct_type)
+{
+  RETURN_VAL_IF_FAIL (struct_type, 0, NULL, NULL, "NULL struct type");
+  return struct_type->get_fields ()->length ();
+}
+
 /* Public entrypoint.  See description in libgccjit.h.
 
    After error-checking, the real work is done by the
@@ -1017,6 +1252,35 @@ gcc_jit_function_get_param (gcc_jit_function *func, int index)
   return static_cast <gcc_jit_param *> (func->get_param (index));
 }
 
+/* Public entrypoint.  See description in libgccjit.h.
+
+   After error-checking, the real work is done by the
+   gcc::jit::recording::function::get_params method, in
+   jit-recording.h.
+  */
+
+size_t
+gcc_jit_function_get_param_count (gcc_jit_function *func)
+{
+  RETURN_VAL_IF_FAIL (func, 0, NULL, NULL, "NULL function");
+  gcc::jit::recording::context *ctxt = func->m_ctxt;
+  JIT_LOG_FUNC (ctxt->get_logger ());
+  return func->get_params ().length ();
+}
+
+/* Public entrypoint.  See description in libgccjit.h.
+
+   After error-checking, the real work is done by the
+   gcc::jit::recording::function::get_return_type method, in
+   jit-recording.h.  */
+
+gcc_jit_type *
+gcc_jit_function_get_return_type (gcc_jit_function *func)
+{
+    RETURN_NULL_IF_FAIL (func, NULL, NULL, "NULL function_type");
+    return (gcc_jit_type *)func->get_return_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 5c722c2c57f..a1c9436c545 100644
--- a/gcc/jit/libgccjit.h
+++ b/gcc/jit/libgccjit.h
@@ -61,6 +61,8 @@ typedef struct gcc_jit_result gcc_jit_result;
 	 +- gcc_jit_location
 	 +- gcc_jit_type
 	    +- gcc_jit_struct
+	    +- gcc_jit_function_type
+	    +- gcc_jit_vector_type
 	 +- gcc_jit_field
 	 +- gcc_jit_function
 	 +- gcc_jit_block
@@ -97,6 +99,12 @@ typedef struct gcc_jit_field gcc_jit_field;
    the layout for, or an opaque type.  */
 typedef struct gcc_jit_struct gcc_jit_struct;
 
+/* A gcc_jit_function_type encapsulates a function type.  */
+typedef struct gcc_jit_function_type gcc_jit_function_type;
+
+/* A gcc_jit_vector_type encapsulates a vector type.  */
+typedef struct gcc_jit_vector_type gcc_jit_vector_type;
+
 /* A gcc_jit_function encapsulates a function: either one that you're
    creating yourself, or a reference to one that you're dynamically
    linking to within the rest of the process.  */
@@ -654,6 +662,15 @@ gcc_jit_struct_set_fields (gcc_jit_struct *struct_type,
 			   int num_fields,
 			   gcc_jit_field **fields);
 
+/* Get a field by index.  */
+extern gcc_jit_field *
+gcc_jit_struct_get_field (gcc_jit_struct *struct_type,
+			   size_t index);
+
+/* Get the number of fields.  */
+extern size_t
+gcc_jit_struct_get_field_count (gcc_jit_struct *struct_type);
+
 /* Unions work similarly to structs.  */
 extern gcc_jit_type *
 gcc_jit_context_new_union_type (gcc_jit_context *ctxt,
@@ -1621,6 +1638,78 @@ gcc_jit_context_add_top_level_asm (gcc_jit_context *ctxt,
 				   gcc_jit_location *loc,
 				   const char *asm_stmts);
 
+#define LIBGCCJIT_HAVE_REFLECTION
+
+/* Reflection functions to get the number of parameters, return type of
+   a function and whether a type is a bool from the C API.
+
+   This API entrypoint was added in LIBGCCJIT_ABI_16; you can test for its
+   presence using
+     #ifdef LIBGCCJIT_HAVE_REFLECTION
+*/
+/* Get the return type of a function.  */
+extern gcc_jit_type *
+gcc_jit_function_get_return_type (gcc_jit_function *func);
+
+/* Get the number of params of a function.  */
+extern size_t
+gcc_jit_function_get_param_count (gcc_jit_function *func);
+
+/* Get the element type of an array type or NULL if it's not an array.  */
+extern gcc_jit_type *
+gcc_jit_type_dyncast_array (gcc_jit_type *type);
+
+/* Return non-zero if the type is a bool.  */
+extern int
+gcc_jit_type_is_bool (gcc_jit_type *type);
+
+/* Return the function type if it is one or NULL.  */
+extern gcc_jit_function_type *
+gcc_jit_type_dyncast_function_ptr_type (gcc_jit_type *type);
+
+/* Given a function type, return its return type.  */
+extern gcc_jit_type *
+gcc_jit_function_type_get_return_type (gcc_jit_function_type *function_type);
+
+/* Given a function type, return its number of parameters.  */
+extern size_t
+gcc_jit_function_type_get_param_count (gcc_jit_function_type *function_type);
+
+/* Given a function type, return the type of the specified parameter.  */
+extern gcc_jit_type *
+gcc_jit_function_type_get_param_type (gcc_jit_function_type *function_type,
+				size_t index);
+
+/* Return non-zero if the type is an integral.  */
+extern int
+gcc_jit_type_is_integral (gcc_jit_type *type);
+
+/* Return the type pointed by the pointer type or NULL if it's not a
+ * pointer.  */
+extern gcc_jit_type *
+gcc_jit_type_is_pointer (gcc_jit_type *type);
+
+/* Given a type, return a dynamic cast to a vector type or NULL.  */
+extern gcc_jit_vector_type *
+gcc_jit_type_dyncast_vector (gcc_jit_type *type);
+
+/* Given a type, return a dynamic cast to a struct type or NULL.  */
+extern gcc_jit_struct *
+gcc_jit_type_is_struct (gcc_jit_type *type);
+
+/* Given a vector type, return the number of units it contains.  */
+extern size_t
+gcc_jit_vector_type_get_num_units (gcc_jit_vector_type *vector_type);
+
+/* Given a vector type, return the type of its elements.  */
+extern gcc_jit_type *
+gcc_jit_vector_type_get_element_type (gcc_jit_vector_type *vector_type);
+
+/* Given a type, return the unqualified type, removing "const", "volatile"
+ * and alignment qualifiers.  */
+extern gcc_jit_type *
+gcc_jit_type_unqualified (gcc_jit_type *type);
+
 #ifdef __cplusplus
 }
 #endif /* __cplusplus */
diff --git a/gcc/jit/libgccjit.map b/gcc/jit/libgccjit.map
index 337ea6c7fe4..64e790949e8 100644
--- a/gcc/jit/libgccjit.map
+++ b/gcc/jit/libgccjit.map
@@ -205,3 +205,24 @@ LIBGCCJIT_ABI_15 {
     gcc_jit_extended_asm_add_clobber;
     gcc_jit_context_add_top_level_asm;
 } LIBGCCJIT_ABI_14;
+
+LIBGCCJIT_ABI_16 {
+  global:
+    gcc_jit_function_get_return_type;
+    gcc_jit_function_get_param_count;
+    gcc_jit_function_type_get_return_type;
+    gcc_jit_function_type_get_param_count;
+    gcc_jit_function_type_get_param_type;
+    gcc_jit_type_unqualified;
+    gcc_jit_type_dyncast_array;
+    gcc_jit_type_is_bool;
+    gcc_jit_type_dyncast_function_ptr_type;
+    gcc_jit_type_is_integral;
+    gcc_jit_type_is_pointer;
+    gcc_jit_type_dyncast_vector;
+    gcc_jit_vector_type_get_element_type;
+    gcc_jit_vector_type_get_num_units;
+    gcc_jit_struct_get_field;
+    gcc_jit_type_is_struct;
+    gcc_jit_struct_get_field_count;
+} LIBGCCJIT_ABI_15;
diff --git a/gcc/testsuite/jit.dg/all-non-failing-tests.h b/gcc/testsuite/jit.dg/all-non-failing-tests.h
index 4202eb7798b..a269144d2df 100644
--- a/gcc/testsuite/jit.dg/all-non-failing-tests.h
+++ b/gcc/testsuite/jit.dg/all-non-failing-tests.h
@@ -258,6 +258,13 @@
 #undef create_code
 #undef verify_code
 
+/* test-reflection.c */
+#define create_code create_code_reflection
+#define verify_code verify_code_reflection
+#include "test-reflection.c"
+#undef create_code
+#undef verify_code
+
 /* test-string-literal.c */
 #define create_code create_code_string_literal
 #define verify_code verify_code_string_literal
@@ -424,6 +431,9 @@ const struct testcase testcases[] = {
   {"reading_struct ",
    create_code_reading_struct ,
    verify_code_reading_struct },
+  {"reflection",
+   create_code_reflection ,
+   verify_code_reflection },
   {"string_literal",
    create_code_string_literal,
    verify_code_string_literal},
diff --git a/gcc/testsuite/jit.dg/test-reflection.c b/gcc/testsuite/jit.dg/test-reflection.c
new file mode 100644
index 00000000000..112a2455c07
--- /dev/null
+++ b/gcc/testsuite/jit.dg/test-reflection.c
@@ -0,0 +1,95 @@
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "libgccjit.h"
+
+#include "harness.h"
+
+void
+create_code (gcc_jit_context *ctxt, void *user_data)
+{
+  /* Do nothing.  */
+}
+
+void
+verify_code (gcc_jit_context *ctxt, gcc_jit_result *result)
+{
+  /* Get the built-in functions.  */
+  gcc_jit_function *builtin_sin =
+    gcc_jit_context_get_builtin_function (ctxt, "sin");
+
+  CHECK_VALUE (gcc_jit_function_get_param_count(builtin_sin), 1);
+
+  gcc_jit_type *double_type =
+    gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_DOUBLE);
+  CHECK_VALUE (gcc_jit_function_get_return_type(builtin_sin), double_type);
+  CHECK (!gcc_jit_type_is_integral(double_type));
+
+  gcc_jit_type *bool_type =
+    gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_BOOL);
+  CHECK (gcc_jit_type_is_bool(bool_type));
+  CHECK (!gcc_jit_type_is_integral(bool_type));
+
+  gcc_jit_type *aligned_bool_type =
+    gcc_jit_type_get_aligned(gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_BOOL), 8);
+  CHECK (gcc_jit_type_is_bool(aligned_bool_type));
+  CHECK (bool_type != aligned_bool_type);
+  CHECK_VALUE (gcc_jit_type_unqualified(aligned_bool_type), bool_type);
+
+  CHECK_VALUE (gcc_jit_type_unqualified(gcc_jit_type_get_const(bool_type)), bool_type);
+  CHECK_VALUE (gcc_jit_type_unqualified(gcc_jit_type_get_volatile(bool_type)), bool_type);
+
+  gcc_jit_type *int64 =
+    gcc_jit_context_get_int_type(ctxt, 8, 1);
+  CHECK (gcc_jit_type_is_integral(int64));
+  gcc_jit_type *uint64 =
+    gcc_jit_context_get_int_type(ctxt, 8, 0);
+  CHECK (gcc_jit_type_is_integral(uint64));
+  gcc_jit_type *int8 =
+    gcc_jit_context_get_int_type(ctxt, 1, 1);
+  CHECK (gcc_jit_type_is_integral(int8));
+  gcc_jit_type *uint8 =
+    gcc_jit_context_get_int_type(ctxt, 1, 0);
+  CHECK (gcc_jit_type_is_integral(uint8));
+
+  CHECK (!gcc_jit_type_dyncast_vector(double_type));
+  gcc_jit_type *vec_type = gcc_jit_type_get_vector (double_type, 4);
+  gcc_jit_vector_type *vector_type = gcc_jit_type_dyncast_vector(vec_type);
+  CHECK (vector_type);
+  CHECK (vec_type != double_type);
+  CHECK_VALUE (gcc_jit_vector_type_get_element_type(vector_type), double_type);
+  CHECK_VALUE (gcc_jit_vector_type_get_num_units(vector_type), 4);
+
+  CHECK (!gcc_jit_type_is_pointer(double_type));
+  CHECK_VALUE (gcc_jit_type_is_pointer(gcc_jit_type_get_pointer(double_type)), double_type);
+
+  gcc_jit_type* params[2] = {int8, uint64};
+  gcc_jit_type *function_ptr_type = gcc_jit_context_new_function_ptr_type(ctxt, NULL, int64, 2, params, 0);
+  CHECK (!gcc_jit_type_dyncast_function_ptr_type (int64));
+  gcc_jit_function_type *function_type = gcc_jit_type_dyncast_function_ptr_type (function_ptr_type);
+  CHECK (function_type);
+  int param_count = gcc_jit_function_type_get_param_count(function_type);
+  CHECK_VALUE (param_count, 2);
+  gcc_jit_type *return_type = gcc_jit_function_type_get_return_type(function_type);
+  CHECK_VALUE (return_type, int64);
+  gcc_jit_type *param1 = gcc_jit_function_type_get_param_type(function_type, 0);
+  CHECK_VALUE (param1, int8);
+  gcc_jit_type *param2 = gcc_jit_function_type_get_param_type(function_type, 1);
+  CHECK_VALUE (param2, uint64);
+
+  gcc_jit_field *field1 = gcc_jit_context_new_field (ctxt, NULL, uint64, "field1");
+  gcc_jit_field *field2 = gcc_jit_context_new_field (ctxt, NULL, double_type, "field2");
+  gcc_jit_field *fields[2] = { field1, field2 };
+  gcc_jit_struct *struct_type = gcc_jit_context_new_struct_type (ctxt, NULL, "testStruct", 2, fields);
+  CHECK_VALUE (gcc_jit_struct_get_field_count(struct_type), 2);
+  CHECK_VALUE (gcc_jit_struct_get_field(struct_type, 0), field1);
+  CHECK_VALUE (gcc_jit_struct_get_field(struct_type, 1), field2);
+  CHECK (!gcc_jit_type_is_struct(double_type));
+  gcc_jit_struct *struct_ty = gcc_jit_type_is_struct(gcc_jit_struct_as_type(struct_type));
+  CHECK_VALUE (struct_ty, struct_type);
+
+  CHECK (!gcc_jit_type_dyncast_array(double_type));
+  gcc_jit_type* array_type = gcc_jit_context_new_array_type(ctxt, NULL, double_type, 1);
+  CHECK_VALUE (gcc_jit_type_dyncast_array(array_type), double_type);
+}
+
-- 
2.33.0


^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re: [PATCH] libgccjit: add some reflection functions in the jit C api
  2021-09-28  0:53                                     ` Antoni Boucher
@ 2021-10-13  2:09                                       ` Antoni Boucher
  2021-10-23 21:20                                         ` SV: " Petter Tomner
  2021-11-14 21:30                                         ` Antoni Boucher
  2021-11-20  0:53                                       ` David Malcolm
  1 sibling, 2 replies; 35+ messages in thread
From: Antoni Boucher @ 2021-10-13  2:09 UTC (permalink / raw)
  To: David Malcolm; +Cc: Antoni Boucher via Jit, gcc-patches

David: PING

Le lundi 27 septembre 2021 à 20:53 -0400, Antoni Boucher a écrit :
> I fixed an issue (it would show an error message when
> gcc_jit_type_dyncast_function_ptr_type was called on a type different
> than a function pointer type).
> 
> Here's the updated patch.
> 
> Le vendredi 18 juin 2021 à 16:37 -0400, David Malcolm a écrit :
> > On Fri, 2021-06-18 at 15:41 -0400, Antoni Boucher wrote:
> > > I have write access now.
> > 
> > Great.
> > 
> > > I'm not sure how I'm supposed to send my patches:
> > > should I put it in personal branches and you'll merge them?
> > 
> > Please send them to this mailing list for review; once they're
> > approved
> > you can merge them.
> > 
> > > 
> > > And for the MAINTAINERS file, should I just push to master right
> > > away,
> > > after sending it to the mailing list?
> > 
> > I think people just push the MAINTAINERS change and then let the
> > list
> > know, since it makes a good test that write access is working
> > correctly.
> > 
> > Dave
> > 
> > > 
> > > Thanks for your help!
> > > 
> > > Le vendredi 18 juin 2021 à 12:09 -0400, David Malcolm a écrit :
> > > > On Fri, 2021-06-18 at 11:55 -0400, Antoni Boucher wrote:
> > > > > Le vendredi 11 juin 2021 à 14:00 -0400, David Malcolm a
> > > > > écrit :
> > > > > > On Fri, 2021-06-11 at 08:15 -0400, Antoni Boucher wrote:
> > > > > > > Thank you for your answer.
> > > > > > > I attached the updated patch.
> > > > > > 
> > > > > > BTW you (or possibly me) dropped the mailing lists; was
> > > > > > that
> > > > > > deliberate?
> > > > > 
> > > > > Oh, my bad.
> > > > > 
> > > > 
> > > > [...]
> > > > 
> > > > 
> > > > > > 
> > > > > > 
> > > > > > > I have signed the FSF copyright attribution.
> > > > > > 
> > > > > > I can push changes on your behalf, but I'd prefer it if you
> > > > > > did
> > > > > > it,
> > > > > > especially given that you have various other patches you
> > > > > > want
> > > > > > to
> > > > > > get
> > > > > > in.
> > > > > > 
> > > > > > Instructions on how to get push rights to the git repo are
> > > > > > here:
> > > > > >   https://gcc.gnu.org/gitwrite.html
> > > > > > 
> > > > > > I can sponsor you.
> > > > > 
> > > > > Thanks.
> > > > > I did sign up to get push rights.
> > > > > Have you accepted my request to get those?
> > > > 
> > > > I did, but I didn't see any kind of notification.  Did you get
> > > > an
> > > > email
> > > > about it?
> > > > 
> > > > 
> > > > Dave
> > > > 
> > > 
> > > 
> > 
> > 
> 



^ permalink raw reply	[flat|nested] 35+ messages in thread

* SV: [PATCH] libgccjit: add some reflection functions in the jit C api
  2021-10-13  2:09                                       ` Antoni Boucher
@ 2021-10-23 21:20                                         ` Petter Tomner
  2021-11-14 21:30                                         ` Antoni Boucher
  1 sibling, 0 replies; 35+ messages in thread
From: Petter Tomner @ 2021-10-23 21:20 UTC (permalink / raw)
  To: David Malcolm, Antoni Boucher; +Cc: jit

Hi! (Sorry, my mail client dropped the jit mailing-list. Resending the mail to it)

+gcc_jit_type *
+gcc_jit_type_unqualified (gcc_jit_type *type)
+{
+  RETURN_NULL_IF_FAIL (type, NULL, NULL, "NULL type");
+
+  return (gcc_jit_type *)type->unqualified ();
+}

I think there is a problem with the current implementation of unqualified() that might be kinda surprising to
users, since it only removes one qualifier and also not "pointed to" qualifiers.

Unrelated to this patch that behavior should probably be documented, since it effects many entry-points
and makes cast to base type kinda mandatory when qualified types are mixed. Casts uses a recursive
check of types and is happy to cast any pointer to any pointer (no matter the level of pointerness) so
they work.

I guess the casts should get some shortcircuit for casts between same base types really,
to not bloat the GENERIC tree.

I made a utility function in another patch for comparing types that do full stripping (see bellow).

Maybe something like that could be usefull?

jit-recording.h:
+/* Strip all qualifiers and count pointer depth, returning true
+   if the types and pointer depth are the same, otherwise false. */
+static inline bool
+types_kinda_same (recording::type *a, recording::type *b)
+{
+  /* Handle trivial case here, to allow for inlining. */
+  return a == b || types_kinda_same_internal (a, b);
+}
jit-recording.c:
+/* Strip qualifiers and count pointer depth, returning true
+   if the types' base type and pointer depth are
+   the same, otherwise false.
+
+   Do not call this directly. Call 'types_kinda_same' */
+bool
+types_kinda_same_internal (recording::type *a, recording::type *b)
+{
+  int ptr_depth[2] = {};
+  recording::type *base_types[2];
+  recording::type *types[2] = {a, b};
+
+  /* Strip qualifiers and count pointerness */
+  for (int i = 0; i < 2; i++)
+    {
+      recording::type *t = types[i];
+      while (true)
+       {
+         if (!t)
+           return false; /* Should only happen on bad input */
+
+         recording::type *pointed_to_type = t->is_pointer();
+         if (pointed_to_type != NULL)
+           {
+             ptr_depth[i]++;
+             t = pointed_to_type;
+             continue;
+           }
+
+         /* unqualified() returns 'this' on base types */
+         recording::type *next = t->unqualified ();
+         if (next == t)
+           {
+             base_types[i] = t;
+             break;
+           }
+         t = next;
+       }
+    }
+
+  return base_types[0] == base_types[1] &&
+    (ptr_depth[0] == ptr_depth[1]);
+}


Från: Jit <jit-bounces+tomner=kth.se@gcc.gnu.org> för Antoni Boucher via Jit <jit@gcc.gnu.org>
Skickat: den 13 oktober 2021 04:09
Till: David Malcolm
Kopia: Antoni Boucher via Jit; gcc-patches@gcc.gnu.org
Ämne: Re: [PATCH] libgccjit: add some reflection functions in the jit C api
    
David: PING

Le lundi 27 septembre 2021 à 20:53 -0400, Antoni Boucher a écrit :
> I fixed an issue (it would show an error message when
> gcc_jit_type_dyncast_function_ptr_type was called on a type different
> than a function pointer type).
> 
> Here's the updated patch.
> 
> Le vendredi 18 juin 2021 à 16:37 -0400, David Malcolm a écrit :
> > On Fri, 2021-06-18 at 15:41 -0400, Antoni Boucher wrote:
> > > I have write access now.
> > 
> > Great.
> > 
> > > I'm not sure how I'm supposed to send my patches:
> > > should I put it in personal branches and you'll merge them?
> > 
> > Please send them to this mailing list for review; once they're
> > approved
> > you can merge them.
> > 
> > > 
> > > And for the MAINTAINERS file, should I just push to master right
> > > away,
> > > after sending it to the mailing list?
> > 
> > I think people just push the MAINTAINERS change and then let the
> > list
> > know, since it makes a good test that write access is working
> > correctly.
> > 
> > Dave
> > 
> > > 
> > > Thanks for your help!
> > > 
> > > Le vendredi 18 juin 2021 à 12:09 -0400, David Malcolm a écrit :
> > > > On Fri, 2021-06-18 at 11:55 -0400, Antoni Boucher wrote:
> > > > > Le vendredi 11 juin 2021 à 14:00 -0400, David Malcolm a
> > > > > écrit :
> > > > > > On Fri, 2021-06-11 at 08:15 -0400, Antoni Boucher wrote:
> > > > > > > Thank you for your answer.
> > > > > > > I attached the updated patch.
> > > > > > 
> > > > > > BTW you (or possibly me) dropped the mailing lists; was
> > > > > > that
> > > > > > deliberate?
> > > > > 
> > > > > Oh, my bad.
> > > > > 
> > > > 
> > > > [...]
> > > > 
> > > > 
> > > > > > 
> > > > > > 
> > > > > > > I have signed the FSF copyright attribution.
> > > > > > 
> > > > > > I can push changes on your behalf, but I'd prefer it if you
> > > > > > did
> > > > > > it,
> > > > > > especially given that you have various other patches you
> > > > > > want
> > > > > > to
> > > > > > get
> > > > > > in.
> > > > > > 
> > > > > > Instructions on how to get push rights to the git repo are
> > > > > > here:
> > > > > >   https://gcc.gnu.org/gitwrite.html
> > > > > > 
> > > > > > I can sponsor you.
> > > > > 
> > > > > Thanks.
> > > > > I did sign up to get push rights.
> > > > > Have you accepted my request to get those?
> > > > 
> > > > I did, but I didn't see any kind of notification.  Did you get
> > > > an
> > > > email
> > > > about it?
> > > > 
> > > > 
> > > > Dave
> > > > 
> > > 
> > > 
> > 
> > 
> 


    

^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re: [PATCH] libgccjit: add some reflection functions in the jit C api
  2021-10-13  2:09                                       ` Antoni Boucher
  2021-10-23 21:20                                         ` SV: " Petter Tomner
@ 2021-11-14 21:30                                         ` Antoni Boucher
  1 sibling, 0 replies; 35+ messages in thread
From: Antoni Boucher @ 2021-11-14 21:30 UTC (permalink / raw)
  To: David Malcolm; +Cc: Antoni Boucher via Jit, gcc-patches

David: PING

Le mardi 12 octobre 2021 à 22:09 -0400, Antoni Boucher a écrit :
> David: PING
> 
> Le lundi 27 septembre 2021 à 20:53 -0400, Antoni Boucher a écrit :
> > I fixed an issue (it would show an error message when
> > gcc_jit_type_dyncast_function_ptr_type was called on a type
> > different
> > than a function pointer type).
> > 
> > Here's the updated patch.
> > 
> > Le vendredi 18 juin 2021 à 16:37 -0400, David Malcolm a écrit :
> > > On Fri, 2021-06-18 at 15:41 -0400, Antoni Boucher wrote:
> > > > I have write access now.
> > > 
> > > Great.
> > > 
> > > > I'm not sure how I'm supposed to send my patches:
> > > > should I put it in personal branches and you'll merge them?
> > > 
> > > Please send them to this mailing list for review; once they're
> > > approved
> > > you can merge them.
> > > 
> > > > 
> > > > And for the MAINTAINERS file, should I just push to master
> > > > right
> > > > away,
> > > > after sending it to the mailing list?
> > > 
> > > I think people just push the MAINTAINERS change and then let the
> > > list
> > > know, since it makes a good test that write access is working
> > > correctly.
> > > 
> > > Dave
> > > 
> > > > 
> > > > Thanks for your help!
> > > > 
> > > > Le vendredi 18 juin 2021 à 12:09 -0400, David Malcolm a écrit :
> > > > > On Fri, 2021-06-18 at 11:55 -0400, Antoni Boucher wrote:
> > > > > > Le vendredi 11 juin 2021 à 14:00 -0400, David Malcolm a
> > > > > > écrit :
> > > > > > > On Fri, 2021-06-11 at 08:15 -0400, Antoni Boucher wrote:
> > > > > > > > Thank you for your answer.
> > > > > > > > I attached the updated patch.
> > > > > > > 
> > > > > > > BTW you (or possibly me) dropped the mailing lists; was
> > > > > > > that
> > > > > > > deliberate?
> > > > > > 
> > > > > > Oh, my bad.
> > > > > > 
> > > > > 
> > > > > [...]
> > > > > 
> > > > > 
> > > > > > > 
> > > > > > > 
> > > > > > > > I have signed the FSF copyright attribution.
> > > > > > > 
> > > > > > > I can push changes on your behalf, but I'd prefer it if
> > > > > > > you
> > > > > > > did
> > > > > > > it,
> > > > > > > especially given that you have various other patches you
> > > > > > > want
> > > > > > > to
> > > > > > > get
> > > > > > > in.
> > > > > > > 
> > > > > > > Instructions on how to get push rights to the git repo
> > > > > > > are
> > > > > > > here:
> > > > > > >   https://gcc.gnu.org/gitwrite.html
> > > > > > > 
> > > > > > > I can sponsor you.
> > > > > > 
> > > > > > Thanks.
> > > > > > I did sign up to get push rights.
> > > > > > Have you accepted my request to get those?
> > > > > 
> > > > > I did, but I didn't see any kind of notification.  Did you
> > > > > get
> > > > > an
> > > > > email
> > > > > about it?
> > > > > 
> > > > > 
> > > > > Dave
> > > > > 
> > > > 
> > > > 
> > > 
> > > 
> > 
> 
> 


^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re: [PATCH] libgccjit: add some reflection functions in the jit C api
  2021-09-28  0:53                                     ` Antoni Boucher
  2021-10-13  2:09                                       ` Antoni Boucher
@ 2021-11-20  0:53                                       ` David Malcolm
  2021-11-26 18:03                                         ` Gerald Pfeifer
  1 sibling, 1 reply; 35+ messages in thread
From: David Malcolm @ 2021-11-20  0:53 UTC (permalink / raw)
  To: Antoni Boucher; +Cc: Antoni Boucher via Jit, gcc-patches

On Mon, 2021-09-27 at 20:53 -0400, Antoni Boucher wrote:
> I fixed an issue (it would show an error message when
> gcc_jit_type_dyncast_function_ptr_type was called on a type different
> than a function pointer type).
> 
> Here's the updated patch.

Sorry about the delay in responding.

The updated patch is good for trunk, assuming you re-ran the regression
tests successfully.

Dave




^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re: [PATCH] libgccjit: add some reflection functions in the jit C api
  2021-11-20  0:53                                       ` David Malcolm
@ 2021-11-26 18:03                                         ` Gerald Pfeifer
  2021-11-26 19:51                                           ` Gerald Pfeifer
  2021-11-27 16:09                                           ` SV: " Petter Tomner
  0 siblings, 2 replies; 35+ messages in thread
From: Gerald Pfeifer @ 2021-11-26 18:03 UTC (permalink / raw)
  To: David Malcolm, Antoni Boucher, Antoni Boucher via Jit; +Cc: gcc-patches

On Fri, 19 Nov 2021, David Malcolm via Gcc-patches wrote:
> On Mon, 2021-09-27 at 20:53 -0400, Antoni Boucher wrote:
>> I fixed an issue (it would show an error message when
>> gcc_jit_type_dyncast_function_ptr_type was called on a type different
>> than a function pointer type).
> The updated patch is good for trunk, assuming you re-ran the regression 
> tests successfully.

I have received a report of GCC builds now failing on FreeBSD/i386:

In function 'gcc_jit_type*
gcc_jit_function_type_get_param_type(gcc_jit_function_type*, size_t)':
/wrkdirs/usr/ports/lang/gcc12-devel/work/gcc-12-20211121/gcc/jit/libgccjit.c:
184:35: error: format '%ld' expects argument of type 'long int', but argument 5 has type 'size_t' {aka 'unsigned int'} [-Werror=format=]
  184 |         jit_error ((CTXT), (LOC), "%s: " ERR_FMT, \
      |                                   ^
  185 |                    __func__, (A0), (A1), (A2));                 \
      |                              ~~~~  
/wrkdirs/usr/ports/lang/gcc12-devel/work/gcc-12-20211121/gcc/jit/libgccjit.c:
230:3: note: in expansion of macro 'RETURN_VAL_IF_FAIL_PRINTF3'
  230 |   RETURN_VAL_IF_FAIL_PRINTF3 (TEST_EXPR, NULL, CTXT, LOC, ERR_FMT, A0, A1, A2)
      |   ^~~~~~~~~~~~~~~~~~~~~~~~~~
/wrkdirs/usr/ports/lang/gcc12-devel/work/gcc-12-20211121/gcc/jit/libgccjit.c: 708:3: note: in expansion of macro 'RETURN_NULL_IF_FAIL_PRINTF3'
  708 |   RETURN_NULL_IF_FAIL_PRINTF3 (index < num_params,
      |   ^~~~~~~~~~~~~~~~~~~~~~~~~~~
/wrkdirs/usr/ports/lang/gcc12-devel/work/gcc-12-20211121/gcc/jit/libgccjit.c: 710:44: note: format string is defined here
  710 |                                "index of %ld is too large (%s has %ld params)",
      |                                          ~~^
      |                                            |
      |                                            long int 
      |                                          %d
/wrkdirs/usr/ports/lang/gcc12-devel/work/gcc-12-20211121/gcc/jit/libgccjit.c:
184:35: error: format '%ld' expects argument of type 'long int', but argument 7 has type 'size_t' {aka 'unsigned int'} [-Werror=format=]


My regular testers are x86-64 and do not show this, but if I'm right
it should also should on 32-bit GNU/Linux?

Gerald

^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re: [PATCH] libgccjit: add some reflection functions in the jit C api
  2021-11-26 18:03                                         ` Gerald Pfeifer
@ 2021-11-26 19:51                                           ` Gerald Pfeifer
  2021-11-27 16:09                                           ` SV: " Petter Tomner
  1 sibling, 0 replies; 35+ messages in thread
From: Gerald Pfeifer @ 2021-11-26 19:51 UTC (permalink / raw)
  To: David Malcolm, Antoni Boucher, Antoni Boucher via Jit; +Cc: gcc-patches

On Fri, 26 Nov 2021, Gerald Pfeifer wrote:
> I have received a report of GCC builds now failing on FreeBSD/i386:

Ah, and here are the logs (IPv6 required, unfortunately):

Log URL:
http://beefy5.nyi.freebsd.org/data/122i386-default/9e1bda400030/logs/gcc12-devel-12.0.0.s20211121.log
Build URL:
http://beefy5.nyi.freebsd.org/build.html?mastername=122i386-default&build=9e1bda400030

Gerald

^ permalink raw reply	[flat|nested] 35+ messages in thread

* SV: [PATCH] libgccjit: add some reflection functions in the jit C api
  2021-11-26 18:03                                         ` Gerald Pfeifer
  2021-11-26 19:51                                           ` Gerald Pfeifer
@ 2021-11-27 16:09                                           ` Petter Tomner
  2021-12-02 18:04                                             ` Gerald Pfeifer
  1 sibling, 1 reply; 35+ messages in thread
From: Petter Tomner @ 2021-11-27 16:09 UTC (permalink / raw)
  To: Gerald Pfeifer, David Malcolm, Antoni Boucher,
	Antoni Boucher via Jit, Antoni Boucher via Jit

> My regular testers are x86-64 and do not show this, but if I'm right it should also should on 32-bit GNU/Linux?

Ye it is supposed to compile cleanly for 32bit too. 

I pushed a patch for it as a "free for all". With %zu specifiers. I hope @dmalcolm is OK with it?

Regards,

Från: Gcc-patches <gcc-patches-bounces+tomner=kth.se@gcc.gnu.org> för Gerald Pfeifer <gerald@pfeifer.com>
Skickat: den 26 november 2021 19:03
Till: David Malcolm; Antoni Boucher; Antoni Boucher via Jit
Kopia: gcc-patches@gcc.gnu.org
Ämne: Re: [PATCH] libgccjit: add some reflection functions in the jit C api
    
On Fri, 19 Nov 2021, David Malcolm via Gcc-patches wrote:
> On Mon, 2021-09-27 at 20:53 -0400, Antoni Boucher wrote:
>> I fixed an issue (it would show an error message when
>> gcc_jit_type_dyncast_function_ptr_type was called on a type different
>> than a function pointer type).
> The updated patch is good for trunk, assuming you re-ran the regression 
> tests successfully.

I have received a report of GCC builds now failing on FreeBSD/i386:

In function 'gcc_jit_type*
gcc_jit_function_type_get_param_type(gcc_jit_function_type*, size_t)':
/wrkdirs/usr/ports/lang/gcc12-devel/work/gcc-12-20211121/gcc/jit/libgccjit.c:
184:35: error: format '%ld' expects argument of type 'long int', but argument 5 has type 'size_t' {aka 'unsigned int'} [-Werror=format=]
  184 |         jit_error ((CTXT), (LOC), "%s: " ERR_FMT, \
      |                                   ^
  185 |                    __func__, (A0), (A1), (A2));                 \
      |                              ~~~~  
/wrkdirs/usr/ports/lang/gcc12-devel/work/gcc-12-20211121/gcc/jit/libgccjit.c:
230:3: note: in expansion of macro 'RETURN_VAL_IF_FAIL_PRINTF3'
  230 |   RETURN_VAL_IF_FAIL_PRINTF3 (TEST_EXPR, NULL, CTXT, LOC, ERR_FMT, A0, A1, A2)
      |   ^~~~~~~~~~~~~~~~~~~~~~~~~~
/wrkdirs/usr/ports/lang/gcc12-devel/work/gcc-12-20211121/gcc/jit/libgccjit.c: 708:3: note: in expansion of macro 'RETURN_NULL_IF_FAIL_PRINTF3'
  708 |   RETURN_NULL_IF_FAIL_PRINTF3 (index < num_params,
      |   ^~~~~~~~~~~~~~~~~~~~~~~~~~~
/wrkdirs/usr/ports/lang/gcc12-devel/work/gcc-12-20211121/gcc/jit/libgccjit.c: 710:44: note: format string is defined here
  710 |                                "index of %ld is too large (%s has %ld params)",
      |                                          ~~^
      |                                            |
      |                                            long int 
      |                                          %d
/wrkdirs/usr/ports/lang/gcc12-devel/work/gcc-12-20211121/gcc/jit/libgccjit.c:
184:35: error: format '%ld' expects argument of type 'long int', but argument 7 has type 'size_t' {aka 'unsigned int'} [-Werror=format=]


My regular testers are x86-64 and do not show this, but if I'm right
it should also should on 32-bit GNU/Linux?

Gerald
    

^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re: [PATCH] libgccjit: add some reflection functions in the jit C api
  2021-11-27 16:09                                           ` SV: " Petter Tomner
@ 2021-12-02 18:04                                             ` Gerald Pfeifer
  0 siblings, 0 replies; 35+ messages in thread
From: Gerald Pfeifer @ 2021-12-02 18:04 UTC (permalink / raw)
  To: Petter Tomner; +Cc: David Malcolm, Antoni Boucher, jit, gcc-patches

On Sat, 27 Nov 2021, Petter Tomner wrote:
> Ye it is supposed to compile cleanly for 32bit too. 
> 
> I pushed a patch for it as a "free for all". With %zu specifiers.

Thank you, Petter.  I just updated the lang/gcc12-devel port in FreeBSD
to Sunday's snapshot that has those changes, so we shall learn soon if
there's still some problem (though I expect we'll be good).

Gerald

^ permalink raw reply	[flat|nested] 35+ messages in thread

end of thread, other threads:[~2021-12-02 18:04 UTC | newest]

Thread overview: 35+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-09-02  1:01 [PATCH] libgccjit: add some reflection functions in the jit C api Antoni Boucher
2020-10-02 20:17 ` David Malcolm
2020-10-02 20:24   ` David Malcolm
2020-10-02 22:39     ` [PATCH] libgccjit: add some reflection functions in the jit C api [PR96889] Antoni Boucher
2020-10-03 18:14     ` [PATCH] libgccjit: add some reflection functions in the jit C api [WIP] Antoni Boucher
2020-10-15 16:02     ` [PATCH] libgccjit: add some reflection functions in the jit C api Antoni Boucher
2020-10-15 16:23       ` Andrea Corallo
2020-10-15 17:39         ` Antoni Boucher
2020-10-15 18:04           ` Andrea Corallo
2020-10-15 21:52           ` David Malcolm
2020-10-17  0:41             ` Antoni Boucher
2020-11-03 22:13             ` Antoni Boucher
2021-05-13  8:33               ` Martin Liška
2021-05-13 21:30               ` David Malcolm
2021-05-14  2:11                 ` Antoni Boucher
2021-05-26  0:19                 ` Antoni Boucher
2021-05-27 22:19                   ` David Malcolm
2021-05-28  1:51                     ` Antoni Boucher
2021-06-10 22:41                       ` David Malcolm
     [not found]                         ` <bc9e81dc3f0a68d6389c9765b5901a5dbd1dcd71.camel@zoho.com>
     [not found]                           ` <e962387aff72bce1ea29b0fc2cb04b84c26f9855.camel@redhat.com>
2021-06-18 15:55                             ` Antoni Boucher
2021-06-18 16:09                               ` David Malcolm
2021-06-18 19:41                                 ` Antoni Boucher
2021-06-18 20:37                                   ` David Malcolm
2021-07-19 16:10                                     ` Antoni Boucher
2021-07-29 12:59                                       ` Antoni Boucher
2021-08-31 12:34                                         ` Antoni Boucher
2021-09-28  0:53                                     ` Antoni Boucher
2021-10-13  2:09                                       ` Antoni Boucher
2021-10-23 21:20                                         ` SV: " Petter Tomner
2021-11-14 21:30                                         ` Antoni Boucher
2021-11-20  0:53                                       ` David Malcolm
2021-11-26 18:03                                         ` Gerald Pfeifer
2021-11-26 19:51                                           ` Gerald Pfeifer
2021-11-27 16:09                                           ` SV: " Petter Tomner
2021-12-02 18:04                                             ` Gerald Pfeifer

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).