public inbox for jit@gcc.gnu.org
 help / color / mirror / Atom feed
* [PATCH] libgccjit: Add support for sized integer types, including 128-bit integers [PR95325]
@ 2021-05-18 12:23 Antoni Boucher
  2021-05-18 12:36 ` Antoni Boucher
  2021-05-18 12:53 ` Jakub Jelinek
  0 siblings, 2 replies; 8+ messages in thread
From: Antoni Boucher @ 2021-05-18 12:23 UTC (permalink / raw)
  To: jit, gcc-patches

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

Hello.
This patch add support for sized integer types.
Maybe it should check whether the size of a byte for the current
platform is 8 bits and do other checks so that they're only available
when it makes sense.
What do you think?
Thanks.

[-- Attachment #2: 0001-Add-support-for-sized-integer-types-including-128-bi.patch --]
[-- Type: text/x-patch, Size: 11816 bytes --]

From d194a03fe3f2e8164c39413b79da9c43e236cf37 Mon Sep 17 00:00:00 2001
From: Antoni Boucher <bouanto@zoho.com>
Date: Mon, 10 May 2021 19:43:02 -0400
Subject: [PATCH] Add support for sized integer types, including 128-bit
 integers [PR95325]

2021-05-18  Antoni Boucher  <bouanto@zoho.com>

    gcc/jit/
            PR target/95325
            * jit-playback.c: Add support for the sized integer types.
            * jit-recording.c: Add support for the sized integer types.
            * libgccjit.h (GCC_JIT_TYPE_UINT8_T, GCC_JIT_TYPE_UINT16_T,
            GCC_JIT_TYPE_UINT32_T, GCC_JIT_TYPE_UINT64_T,
            GCC_JIT_TYPE_UINT128_T, GCC_JIT_TYPE_INT8_T, GCC_JIT_TYPE_INT16_T,
            GCC_JIT_TYPE_INT32_T, GCC_JIT_TYPE_INT64_T, GCC_JIT_TYPE_INT128_T):
            New enum variants for gcc_jit_types.
    gcc/testsuite/
            PR target/95325
            * jit.dg/test-types.c: Add tests for sized integer types.
---
 gcc/jit/jit-playback.c            |  21 ++++++
 gcc/jit/jit-recording.c           |  73 ++++++++++++++++++++
 gcc/jit/libgccjit.h               |  11 +++
 gcc/testsuite/jit.dg/test-types.c | 111 ++++++++++++++++++++++++++++++
 4 files changed, 216 insertions(+)

diff --git a/gcc/jit/jit-playback.c b/gcc/jit/jit-playback.c
index c6136301243..40630aa1ab8 100644
--- a/gcc/jit/jit-playback.c
+++ b/gcc/jit/jit-playback.c
@@ -193,6 +193,27 @@ get_tree_node_for_type (enum gcc_jit_types type_)
     case GCC_JIT_TYPE_UNSIGNED_INT:
       return unsigned_type_node;
 
+    case GCC_JIT_TYPE_UINT8_T:
+      return unsigned_intQI_type_node;
+    case GCC_JIT_TYPE_UINT16_T:
+      return uint16_type_node;
+    case GCC_JIT_TYPE_UINT32_T:
+      return uint32_type_node;
+    case GCC_JIT_TYPE_UINT64_T:
+      return uint64_type_node;
+    case GCC_JIT_TYPE_UINT128_T:
+      return uint128_type_node;
+    case GCC_JIT_TYPE_INT8_T:
+      return intQI_type_node;
+    case GCC_JIT_TYPE_INT16_T:
+      return intHI_type_node;
+    case GCC_JIT_TYPE_INT32_T:
+      return intSI_type_node;
+    case GCC_JIT_TYPE_INT64_T:
+      return intDI_type_node;
+    case GCC_JIT_TYPE_INT128_T:
+      return intTI_type_node;
+
     case GCC_JIT_TYPE_LONG:
       return long_integer_type_node;
     case GCC_JIT_TYPE_UNSIGNED_LONG:
diff --git a/gcc/jit/jit-recording.c b/gcc/jit/jit-recording.c
index 117ff70114c..b67ae8bfb78 100644
--- a/gcc/jit/jit-recording.c
+++ b/gcc/jit/jit-recording.c
@@ -2247,6 +2247,18 @@ recording::memento_of_get_type::get_size ()
     case GCC_JIT_TYPE_UNSIGNED_LONG_LONG:
       size = LONG_LONG_TYPE_SIZE;
       break;
+    case GCC_JIT_TYPE_UINT8_T:
+    case GCC_JIT_TYPE_UINT16_T:
+    case GCC_JIT_TYPE_UINT32_T:
+    case GCC_JIT_TYPE_UINT64_T:
+    case GCC_JIT_TYPE_UINT128_T:
+    case GCC_JIT_TYPE_INT8_T:
+    case GCC_JIT_TYPE_INT16_T:
+    case GCC_JIT_TYPE_INT32_T:
+    case GCC_JIT_TYPE_INT64_T:
+    case GCC_JIT_TYPE_INT128_T:
+      size = 128;
+      break;
     case GCC_JIT_TYPE_FLOAT:
       size = FLOAT_TYPE_SIZE;
       break;
@@ -2295,6 +2307,16 @@ recording::memento_of_get_type::dereference ()
     case GCC_JIT_TYPE_UNSIGNED_LONG:
     case GCC_JIT_TYPE_LONG_LONG:
     case GCC_JIT_TYPE_UNSIGNED_LONG_LONG:
+    case GCC_JIT_TYPE_UINT8_T:
+    case GCC_JIT_TYPE_UINT16_T:
+    case GCC_JIT_TYPE_UINT32_T:
+    case GCC_JIT_TYPE_UINT64_T:
+    case GCC_JIT_TYPE_UINT128_T:
+    case GCC_JIT_TYPE_INT8_T:
+    case GCC_JIT_TYPE_INT16_T:
+    case GCC_JIT_TYPE_INT32_T:
+    case GCC_JIT_TYPE_INT64_T:
+    case GCC_JIT_TYPE_INT128_T:
     case GCC_JIT_TYPE_FLOAT:
     case GCC_JIT_TYPE_DOUBLE:
     case GCC_JIT_TYPE_LONG_DOUBLE:
@@ -2347,6 +2369,16 @@ recording::memento_of_get_type::is_int () const
     case GCC_JIT_TYPE_UNSIGNED_LONG:
     case GCC_JIT_TYPE_LONG_LONG:
     case GCC_JIT_TYPE_UNSIGNED_LONG_LONG:
+    case GCC_JIT_TYPE_UINT8_T:
+    case GCC_JIT_TYPE_UINT16_T:
+    case GCC_JIT_TYPE_UINT32_T:
+    case GCC_JIT_TYPE_UINT64_T:
+    case GCC_JIT_TYPE_UINT128_T:
+    case GCC_JIT_TYPE_INT8_T:
+    case GCC_JIT_TYPE_INT16_T:
+    case GCC_JIT_TYPE_INT32_T:
+    case GCC_JIT_TYPE_INT64_T:
+    case GCC_JIT_TYPE_INT128_T:
       return true;
 
     case GCC_JIT_TYPE_FLOAT:
@@ -2400,6 +2432,16 @@ recording::memento_of_get_type::is_float () const
     case GCC_JIT_TYPE_UNSIGNED_LONG:
     case GCC_JIT_TYPE_LONG_LONG:
     case GCC_JIT_TYPE_UNSIGNED_LONG_LONG:
+    case GCC_JIT_TYPE_UINT8_T:
+    case GCC_JIT_TYPE_UINT16_T:
+    case GCC_JIT_TYPE_UINT32_T:
+    case GCC_JIT_TYPE_UINT64_T:
+    case GCC_JIT_TYPE_UINT128_T:
+    case GCC_JIT_TYPE_INT8_T:
+    case GCC_JIT_TYPE_INT16_T:
+    case GCC_JIT_TYPE_INT32_T:
+    case GCC_JIT_TYPE_INT64_T:
+    case GCC_JIT_TYPE_INT128_T:
       return false;
 
     case GCC_JIT_TYPE_FLOAT:
@@ -2453,6 +2495,16 @@ recording::memento_of_get_type::is_bool () const
     case GCC_JIT_TYPE_UNSIGNED_LONG:
     case GCC_JIT_TYPE_LONG_LONG:
     case GCC_JIT_TYPE_UNSIGNED_LONG_LONG:
+    case GCC_JIT_TYPE_UINT8_T:
+    case GCC_JIT_TYPE_UINT16_T:
+    case GCC_JIT_TYPE_UINT32_T:
+    case GCC_JIT_TYPE_UINT64_T:
+    case GCC_JIT_TYPE_UINT128_T:
+    case GCC_JIT_TYPE_INT8_T:
+    case GCC_JIT_TYPE_INT16_T:
+    case GCC_JIT_TYPE_INT32_T:
+    case GCC_JIT_TYPE_INT64_T:
+    case GCC_JIT_TYPE_INT128_T:
       return false;
 
     case GCC_JIT_TYPE_FLOAT:
@@ -2511,6 +2563,17 @@ static const char * const get_type_strings[] = {
   "long long",           /* GCC_JIT_TYPE_LONG_LONG */
   "unsigned long long",  /* GCC_JIT_TYPE_UNSIGNED_LONG_LONG */
 
+  "__uint8_t",    /* GCC_JIT_TYPE_UINT8_T */
+  "__uint16_t",   /* GCC_JIT_TYPE_UINT16_T */
+  "__uint32_t",   /* GCC_JIT_TYPE_UINT32_T */
+  "__uint64_t",   /* GCC_JIT_TYPE_UINT64_T */
+  "__uint128_t",  /* GCC_JIT_TYPE_UINT128_T */
+  "__int8_t",     /* GCC_JIT_TYPE_INT8_T */
+  "__int16_t",    /* GCC_JIT_TYPE_INT16_T */
+  "__int32_t",    /* GCC_JIT_TYPE_INT32_T */
+  "__int64_t",    /* GCC_JIT_TYPE_INT64_T */
+  "__int128_t",   /* GCC_JIT_TYPE_INT128_T */
+
   "float",        /* GCC_JIT_TYPE_FLOAT */
   "double",       /* GCC_JIT_TYPE_DOUBLE */
   "long double",  /* GCC_JIT_TYPE_LONG_DOUBLE */
@@ -2551,6 +2614,16 @@ static const char * const get_type_enum_strings[] = {
   "GCC_JIT_TYPE_UNSIGNED_LONG",
   "GCC_JIT_TYPE_LONG_LONG",
   "GCC_JIT_TYPE_UNSIGNED_LONG_LONG",
+  "GCC_JIT_TYPE_UINT8_T",
+  "GCC_JIT_TYPE_UINT16_T",
+  "GCC_JIT_TYPE_UINT32_T",
+  "GCC_JIT_TYPE_UINT64_T",
+  "GCC_JIT_TYPE_UINT128_T",
+  "GCC_JIT_TYPE_INT8_T",
+  "GCC_JIT_TYPE_INT16_T",
+  "GCC_JIT_TYPE_INT32_T",
+  "GCC_JIT_TYPE_INT64_T",
+  "GCC_JIT_TYPE_INT128_T",
   "GCC_JIT_TYPE_FLOAT",
   "GCC_JIT_TYPE_DOUBLE",
   "GCC_JIT_TYPE_LONG_DOUBLE",
diff --git a/gcc/jit/libgccjit.h b/gcc/jit/libgccjit.h
index 5c722c2c57f..5d88033a2ab 100644
--- a/gcc/jit/libgccjit.h
+++ b/gcc/jit/libgccjit.h
@@ -548,6 +548,17 @@ enum gcc_jit_types
   GCC_JIT_TYPE_LONG_LONG, /* signed */
   GCC_JIT_TYPE_UNSIGNED_LONG_LONG,
 
+  GCC_JIT_TYPE_UINT8_T,
+  GCC_JIT_TYPE_UINT16_T,
+  GCC_JIT_TYPE_UINT32_T,
+  GCC_JIT_TYPE_UINT64_T,
+  GCC_JIT_TYPE_UINT128_T,
+  GCC_JIT_TYPE_INT8_T,
+  GCC_JIT_TYPE_INT16_T,
+  GCC_JIT_TYPE_INT32_T,
+  GCC_JIT_TYPE_INT64_T,
+  GCC_JIT_TYPE_INT128_T,
+
   /* Floating-point types  */
 
   GCC_JIT_TYPE_FLOAT,
diff --git a/gcc/testsuite/jit.dg/test-types.c b/gcc/testsuite/jit.dg/test-types.c
index 8debcd7eb82..9c66284f193 100644
--- a/gcc/testsuite/jit.dg/test-types.c
+++ b/gcc/testsuite/jit.dg/test-types.c
@@ -1,3 +1,4 @@
+#include <stdint.h>
 #include <stdlib.h>
 #include <stdio.h>
 #include <stddef.h>
@@ -29,6 +30,18 @@ struct zoo
   long long m_long_long;
   unsigned long long m_unsigned_long_long;
 
+  uint8_t m_u8;
+  uint16_t m_u16;
+  uint32_t m_u32;
+  uint64_t m_u64;
+  __uint128_t m_u128;
+
+  int8_t m_i8;
+  int16_t m_i16;
+  int32_t m_i32;
+  int64_t m_i64;
+  __int128_t m_i128;
+
   int m_sized_int_type;
 
   float m_float;
@@ -101,6 +114,28 @@ create_code (gcc_jit_context *ctxt, void *user_data)
   gcc_jit_field *field_m_unsigned_long_long =
     CREATE_FIELD (GCC_JIT_TYPE_UNSIGNED_LONG_LONG, "m_unsigned_long_long");
 
+  gcc_jit_field *field_m_u8 =
+    CREATE_FIELD (GCC_JIT_TYPE_UINT8_T, "m_u8");
+  gcc_jit_field *field_m_u16 =
+    CREATE_FIELD (GCC_JIT_TYPE_UINT16_T, "m_u16");
+  gcc_jit_field *field_m_u32 =
+    CREATE_FIELD (GCC_JIT_TYPE_UINT32_T, "m_u32");
+  gcc_jit_field *field_m_u64 =
+    CREATE_FIELD (GCC_JIT_TYPE_UINT64_T, "m_u64");
+  gcc_jit_field *field_m_u128 =
+    CREATE_FIELD (GCC_JIT_TYPE_UINT128_T, "m_u128");
+
+  gcc_jit_field *field_m_i8 =
+    CREATE_FIELD (GCC_JIT_TYPE_INT8_T, "m_i8");
+  gcc_jit_field *field_m_i16 =
+    CREATE_FIELD (GCC_JIT_TYPE_INT16_T, "m_i16");
+  gcc_jit_field *field_m_i32 =
+    CREATE_FIELD (GCC_JIT_TYPE_INT32_T, "m_i32");
+  gcc_jit_field *field_m_i64 =
+    CREATE_FIELD (GCC_JIT_TYPE_INT64_T, "m_i64");
+  gcc_jit_field *field_m_i128 =
+    CREATE_FIELD (GCC_JIT_TYPE_INT128_T, "m_i128");
+
   /* Signed int type with sizeof (int): */
   gcc_jit_type *sized_int_type =
     gcc_jit_context_get_int_type (ctxt, sizeof (int), 1);
@@ -147,6 +182,18 @@ create_code (gcc_jit_context *ctxt, void *user_data)
     field_m_long_long,
     field_m_unsigned_long_long,
 
+    field_m_u8,
+    field_m_u16,
+    field_m_u32,
+    field_m_u64,
+    field_m_u128,
+
+    field_m_i8,
+    field_m_i16,
+    field_m_i32,
+    field_m_i64,
+    field_m_i128,
+
     field_m_sized_int_type,
 
     field_m_float,
@@ -266,6 +313,58 @@ create_code (gcc_jit_context *ctxt, void *user_data)
       gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_UNSIGNED_LONG_LONG),
       123456789))
 
+  ASSIGN(field_m_u8,
+    gcc_jit_context_new_rvalue_from_int (
+      ctxt,
+      gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_UINT8_T),
+      123))
+  ASSIGN(field_m_u16,
+    gcc_jit_context_new_rvalue_from_int (
+      ctxt,
+      gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_UINT16_T),
+      12345))
+  ASSIGN(field_m_u32,
+    gcc_jit_context_new_rvalue_from_int (
+      ctxt,
+      gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_UINT32_T),
+      123456789))
+  ASSIGN(field_m_u64,
+    gcc_jit_context_new_rvalue_from_int (
+      ctxt,
+      gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_UINT64_T),
+      123456789))
+  ASSIGN(field_m_u128,
+    gcc_jit_context_new_rvalue_from_int (
+      ctxt,
+      gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_UINT128_T),
+      123456789))
+
+  ASSIGN(field_m_i8,
+    gcc_jit_context_new_rvalue_from_int (
+      ctxt,
+      gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_INT8_T),
+      -1))
+  ASSIGN(field_m_i16,
+    gcc_jit_context_new_rvalue_from_int (
+      ctxt,
+      gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_INT16_T),
+      -2))
+  ASSIGN(field_m_i32,
+    gcc_jit_context_new_rvalue_from_int (
+      ctxt,
+      gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_INT32_T),
+      -3))
+  ASSIGN(field_m_i64,
+    gcc_jit_context_new_rvalue_from_int (
+      ctxt,
+      gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_INT64_T),
+      -4))
+  ASSIGN(field_m_i128,
+    gcc_jit_context_new_rvalue_from_int (
+      ctxt,
+      gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_INT128_T),
+      -5))
+
   ASSIGN(field_m_sized_int_type,
     gcc_jit_context_new_rvalue_from_int (
       ctxt,
@@ -347,6 +446,18 @@ verify_code (gcc_jit_context *ctxt, gcc_jit_result *result)
   CHECK_VALUE (z.m_long_long, -42);
   CHECK_VALUE (z.m_unsigned_long_long, 123456789);
 
+  CHECK_VALUE (z.m_u8, 123);
+  CHECK_VALUE (z.m_u16, 12345);
+  CHECK_VALUE (z.m_u32, 123456789);
+  CHECK_VALUE (z.m_u64, 123456789);
+  CHECK_VALUE (z.m_u128, 123456789);
+
+  CHECK_VALUE (z.m_i8, -1);
+  CHECK_VALUE (z.m_i16, -2);
+  CHECK_VALUE (z.m_i32, -3);
+  CHECK_VALUE (z.m_i64, -4);
+  CHECK_VALUE (z.m_i128, -5);
+
   CHECK_VALUE (z.m_sized_int_type, 500);
 
   CHECK_VALUE (z.m_float, 3.141f);
-- 
2.31.1


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

* Re: [PATCH] libgccjit: Add support for sized integer types, including 128-bit integers [PR95325]
  2021-05-18 12:23 [PATCH] libgccjit: Add support for sized integer types, including 128-bit integers [PR95325] Antoni Boucher
@ 2021-05-18 12:36 ` Antoni Boucher
  2021-05-18 12:53 ` Jakub Jelinek
  1 sibling, 0 replies; 8+ messages in thread
From: Antoni Boucher @ 2021-05-18 12:36 UTC (permalink / raw)
  To: jit, gcc-patches

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

I had forgotten to update the documentation.
This new patch contains it.

Le mardi 18 mai 2021 à 08:23 -0400, Antoni Boucher a écrit :
> Hello.
> This patch add support for sized integer types.
> Maybe it should check whether the size of a byte for the current
> platform is 8 bits and do other checks so that they're only available
> when it makes sense.
> What do you think?
> Thanks.


[-- Attachment #2: 0001-Add-support-for-sized-integer-types-including-128-bi.patch --]
[-- Type: text/x-patch, Size: 13425 bytes --]

From 05d931244a575f3d03d8c7ff409d539e0cc6d154 Mon Sep 17 00:00:00 2001
From: Antoni Boucher <bouanto@zoho.com>
Date: Mon, 10 May 2021 19:43:02 -0400
Subject: [PATCH] Add support for sized integer types, including 128-bit
 integers [PR95325]

2021-05-18  Antoni Boucher  <bouanto@zoho.com>

    gcc/jit/
            PR target/95325
            * docs/topics/types.rst: Add documentation for the new types
            GCC_JIT_TYPE_UINT8_T, GCC_JIT_TYPE_UINT16_T,
            GCC_JIT_TYPE_UINT32_T, GCC_JIT_TYPE_UINT64_T,
            GCC_JIT_TYPE_UINT128_T, GCC_JIT_TYPE_INT8_T, GCC_JIT_TYPE_INT16_T,
            GCC_JIT_TYPE_INT32_T, GCC_JIT_TYPE_INT64_T, GCC_JIT_TYPE_INT128_T.
            * jit-playback.c: Add support for the sized integer types.
            * jit-recording.c: Add support for the sized integer types.
            * libgccjit.h (GCC_JIT_TYPE_UINT8_T, GCC_JIT_TYPE_UINT16_T,
            GCC_JIT_TYPE_UINT32_T, GCC_JIT_TYPE_UINT64_T,
            GCC_JIT_TYPE_UINT128_T, GCC_JIT_TYPE_INT8_T, GCC_JIT_TYPE_INT16_T,
            GCC_JIT_TYPE_INT32_T, GCC_JIT_TYPE_INT64_T, GCC_JIT_TYPE_INT128_T):
            New enum variants for gcc_jit_types.
    gcc/testsuite/
            PR target/95325
            * jit.dg/test-types.c: Add tests for sized integer types.
---
 gcc/jit/docs/topics/types.rst     |  10 +++
 gcc/jit/jit-playback.c            |  21 ++++++
 gcc/jit/jit-recording.c           |  73 ++++++++++++++++++++
 gcc/jit/libgccjit.h               |  11 +++
 gcc/testsuite/jit.dg/test-types.c | 111 ++++++++++++++++++++++++++++++
 5 files changed, 226 insertions(+)

diff --git a/gcc/jit/docs/topics/types.rst b/gcc/jit/docs/topics/types.rst
index 831f11b679a..68accacca45 100644
--- a/gcc/jit/docs/topics/types.rst
+++ b/gcc/jit/docs/topics/types.rst
@@ -76,6 +76,16 @@ Standard types
    :c:data:`GCC_JIT_TYPE_UNSIGNED_LONG`        C's ``unsigned long``
    :c:data:`GCC_JIT_TYPE_LONG_LONG`            C99's ``long long`` (signed)
    :c:data:`GCC_JIT_TYPE_UNSIGNED_LONG_LONG`   C99's ``unsigned long long``
+   :c:data:`GCC_JIT_TYPE_UINT8_T`              C99's ``uint8_t``
+   :c:data:`GCC_JIT_TYPE_UINT16_T`             C99's ``uint16_t``
+   :c:data:`GCC_JIT_TYPE_UINT32_T`             C99's ``uint32_t``
+   :c:data:`GCC_JIT_TYPE_UINT64_T`             C99's ``uint64_t``
+   :c:data:`GCC_JIT_TYPE_UINT128_T`            C99's ``__uint128_t``
+   :c:data:`GCC_JIT_TYPE_INT8_T`               C99's ``int8_t``
+   :c:data:`GCC_JIT_TYPE_INT16_T`              C99's ``int16_t``
+   :c:data:`GCC_JIT_TYPE_INT32_T`              C99's ``int32_t``
+   :c:data:`GCC_JIT_TYPE_INT64_T`              C99's ``int64_t``
+   :c:data:`GCC_JIT_TYPE_INT128_T`             C99's ``__int128_t``
    :c:data:`GCC_JIT_TYPE_FLOAT`
    :c:data:`GCC_JIT_TYPE_DOUBLE`
    :c:data:`GCC_JIT_TYPE_LONG_DOUBLE`
diff --git a/gcc/jit/jit-playback.c b/gcc/jit/jit-playback.c
index c6136301243..40630aa1ab8 100644
--- a/gcc/jit/jit-playback.c
+++ b/gcc/jit/jit-playback.c
@@ -193,6 +193,27 @@ get_tree_node_for_type (enum gcc_jit_types type_)
     case GCC_JIT_TYPE_UNSIGNED_INT:
       return unsigned_type_node;
 
+    case GCC_JIT_TYPE_UINT8_T:
+      return unsigned_intQI_type_node;
+    case GCC_JIT_TYPE_UINT16_T:
+      return uint16_type_node;
+    case GCC_JIT_TYPE_UINT32_T:
+      return uint32_type_node;
+    case GCC_JIT_TYPE_UINT64_T:
+      return uint64_type_node;
+    case GCC_JIT_TYPE_UINT128_T:
+      return uint128_type_node;
+    case GCC_JIT_TYPE_INT8_T:
+      return intQI_type_node;
+    case GCC_JIT_TYPE_INT16_T:
+      return intHI_type_node;
+    case GCC_JIT_TYPE_INT32_T:
+      return intSI_type_node;
+    case GCC_JIT_TYPE_INT64_T:
+      return intDI_type_node;
+    case GCC_JIT_TYPE_INT128_T:
+      return intTI_type_node;
+
     case GCC_JIT_TYPE_LONG:
       return long_integer_type_node;
     case GCC_JIT_TYPE_UNSIGNED_LONG:
diff --git a/gcc/jit/jit-recording.c b/gcc/jit/jit-recording.c
index 117ff70114c..b67ae8bfb78 100644
--- a/gcc/jit/jit-recording.c
+++ b/gcc/jit/jit-recording.c
@@ -2247,6 +2247,18 @@ recording::memento_of_get_type::get_size ()
     case GCC_JIT_TYPE_UNSIGNED_LONG_LONG:
       size = LONG_LONG_TYPE_SIZE;
       break;
+    case GCC_JIT_TYPE_UINT8_T:
+    case GCC_JIT_TYPE_UINT16_T:
+    case GCC_JIT_TYPE_UINT32_T:
+    case GCC_JIT_TYPE_UINT64_T:
+    case GCC_JIT_TYPE_UINT128_T:
+    case GCC_JIT_TYPE_INT8_T:
+    case GCC_JIT_TYPE_INT16_T:
+    case GCC_JIT_TYPE_INT32_T:
+    case GCC_JIT_TYPE_INT64_T:
+    case GCC_JIT_TYPE_INT128_T:
+      size = 128;
+      break;
     case GCC_JIT_TYPE_FLOAT:
       size = FLOAT_TYPE_SIZE;
       break;
@@ -2295,6 +2307,16 @@ recording::memento_of_get_type::dereference ()
     case GCC_JIT_TYPE_UNSIGNED_LONG:
     case GCC_JIT_TYPE_LONG_LONG:
     case GCC_JIT_TYPE_UNSIGNED_LONG_LONG:
+    case GCC_JIT_TYPE_UINT8_T:
+    case GCC_JIT_TYPE_UINT16_T:
+    case GCC_JIT_TYPE_UINT32_T:
+    case GCC_JIT_TYPE_UINT64_T:
+    case GCC_JIT_TYPE_UINT128_T:
+    case GCC_JIT_TYPE_INT8_T:
+    case GCC_JIT_TYPE_INT16_T:
+    case GCC_JIT_TYPE_INT32_T:
+    case GCC_JIT_TYPE_INT64_T:
+    case GCC_JIT_TYPE_INT128_T:
     case GCC_JIT_TYPE_FLOAT:
     case GCC_JIT_TYPE_DOUBLE:
     case GCC_JIT_TYPE_LONG_DOUBLE:
@@ -2347,6 +2369,16 @@ recording::memento_of_get_type::is_int () const
     case GCC_JIT_TYPE_UNSIGNED_LONG:
     case GCC_JIT_TYPE_LONG_LONG:
     case GCC_JIT_TYPE_UNSIGNED_LONG_LONG:
+    case GCC_JIT_TYPE_UINT8_T:
+    case GCC_JIT_TYPE_UINT16_T:
+    case GCC_JIT_TYPE_UINT32_T:
+    case GCC_JIT_TYPE_UINT64_T:
+    case GCC_JIT_TYPE_UINT128_T:
+    case GCC_JIT_TYPE_INT8_T:
+    case GCC_JIT_TYPE_INT16_T:
+    case GCC_JIT_TYPE_INT32_T:
+    case GCC_JIT_TYPE_INT64_T:
+    case GCC_JIT_TYPE_INT128_T:
       return true;
 
     case GCC_JIT_TYPE_FLOAT:
@@ -2400,6 +2432,16 @@ recording::memento_of_get_type::is_float () const
     case GCC_JIT_TYPE_UNSIGNED_LONG:
     case GCC_JIT_TYPE_LONG_LONG:
     case GCC_JIT_TYPE_UNSIGNED_LONG_LONG:
+    case GCC_JIT_TYPE_UINT8_T:
+    case GCC_JIT_TYPE_UINT16_T:
+    case GCC_JIT_TYPE_UINT32_T:
+    case GCC_JIT_TYPE_UINT64_T:
+    case GCC_JIT_TYPE_UINT128_T:
+    case GCC_JIT_TYPE_INT8_T:
+    case GCC_JIT_TYPE_INT16_T:
+    case GCC_JIT_TYPE_INT32_T:
+    case GCC_JIT_TYPE_INT64_T:
+    case GCC_JIT_TYPE_INT128_T:
       return false;
 
     case GCC_JIT_TYPE_FLOAT:
@@ -2453,6 +2495,16 @@ recording::memento_of_get_type::is_bool () const
     case GCC_JIT_TYPE_UNSIGNED_LONG:
     case GCC_JIT_TYPE_LONG_LONG:
     case GCC_JIT_TYPE_UNSIGNED_LONG_LONG:
+    case GCC_JIT_TYPE_UINT8_T:
+    case GCC_JIT_TYPE_UINT16_T:
+    case GCC_JIT_TYPE_UINT32_T:
+    case GCC_JIT_TYPE_UINT64_T:
+    case GCC_JIT_TYPE_UINT128_T:
+    case GCC_JIT_TYPE_INT8_T:
+    case GCC_JIT_TYPE_INT16_T:
+    case GCC_JIT_TYPE_INT32_T:
+    case GCC_JIT_TYPE_INT64_T:
+    case GCC_JIT_TYPE_INT128_T:
       return false;
 
     case GCC_JIT_TYPE_FLOAT:
@@ -2511,6 +2563,17 @@ static const char * const get_type_strings[] = {
   "long long",           /* GCC_JIT_TYPE_LONG_LONG */
   "unsigned long long",  /* GCC_JIT_TYPE_UNSIGNED_LONG_LONG */
 
+  "__uint8_t",    /* GCC_JIT_TYPE_UINT8_T */
+  "__uint16_t",   /* GCC_JIT_TYPE_UINT16_T */
+  "__uint32_t",   /* GCC_JIT_TYPE_UINT32_T */
+  "__uint64_t",   /* GCC_JIT_TYPE_UINT64_T */
+  "__uint128_t",  /* GCC_JIT_TYPE_UINT128_T */
+  "__int8_t",     /* GCC_JIT_TYPE_INT8_T */
+  "__int16_t",    /* GCC_JIT_TYPE_INT16_T */
+  "__int32_t",    /* GCC_JIT_TYPE_INT32_T */
+  "__int64_t",    /* GCC_JIT_TYPE_INT64_T */
+  "__int128_t",   /* GCC_JIT_TYPE_INT128_T */
+
   "float",        /* GCC_JIT_TYPE_FLOAT */
   "double",       /* GCC_JIT_TYPE_DOUBLE */
   "long double",  /* GCC_JIT_TYPE_LONG_DOUBLE */
@@ -2551,6 +2614,16 @@ static const char * const get_type_enum_strings[] = {
   "GCC_JIT_TYPE_UNSIGNED_LONG",
   "GCC_JIT_TYPE_LONG_LONG",
   "GCC_JIT_TYPE_UNSIGNED_LONG_LONG",
+  "GCC_JIT_TYPE_UINT8_T",
+  "GCC_JIT_TYPE_UINT16_T",
+  "GCC_JIT_TYPE_UINT32_T",
+  "GCC_JIT_TYPE_UINT64_T",
+  "GCC_JIT_TYPE_UINT128_T",
+  "GCC_JIT_TYPE_INT8_T",
+  "GCC_JIT_TYPE_INT16_T",
+  "GCC_JIT_TYPE_INT32_T",
+  "GCC_JIT_TYPE_INT64_T",
+  "GCC_JIT_TYPE_INT128_T",
   "GCC_JIT_TYPE_FLOAT",
   "GCC_JIT_TYPE_DOUBLE",
   "GCC_JIT_TYPE_LONG_DOUBLE",
diff --git a/gcc/jit/libgccjit.h b/gcc/jit/libgccjit.h
index 5c722c2c57f..5d88033a2ab 100644
--- a/gcc/jit/libgccjit.h
+++ b/gcc/jit/libgccjit.h
@@ -548,6 +548,17 @@ enum gcc_jit_types
   GCC_JIT_TYPE_LONG_LONG, /* signed */
   GCC_JIT_TYPE_UNSIGNED_LONG_LONG,
 
+  GCC_JIT_TYPE_UINT8_T,
+  GCC_JIT_TYPE_UINT16_T,
+  GCC_JIT_TYPE_UINT32_T,
+  GCC_JIT_TYPE_UINT64_T,
+  GCC_JIT_TYPE_UINT128_T,
+  GCC_JIT_TYPE_INT8_T,
+  GCC_JIT_TYPE_INT16_T,
+  GCC_JIT_TYPE_INT32_T,
+  GCC_JIT_TYPE_INT64_T,
+  GCC_JIT_TYPE_INT128_T,
+
   /* Floating-point types  */
 
   GCC_JIT_TYPE_FLOAT,
diff --git a/gcc/testsuite/jit.dg/test-types.c b/gcc/testsuite/jit.dg/test-types.c
index 8debcd7eb82..9c66284f193 100644
--- a/gcc/testsuite/jit.dg/test-types.c
+++ b/gcc/testsuite/jit.dg/test-types.c
@@ -1,3 +1,4 @@
+#include <stdint.h>
 #include <stdlib.h>
 #include <stdio.h>
 #include <stddef.h>
@@ -29,6 +30,18 @@ struct zoo
   long long m_long_long;
   unsigned long long m_unsigned_long_long;
 
+  uint8_t m_u8;
+  uint16_t m_u16;
+  uint32_t m_u32;
+  uint64_t m_u64;
+  __uint128_t m_u128;
+
+  int8_t m_i8;
+  int16_t m_i16;
+  int32_t m_i32;
+  int64_t m_i64;
+  __int128_t m_i128;
+
   int m_sized_int_type;
 
   float m_float;
@@ -101,6 +114,28 @@ create_code (gcc_jit_context *ctxt, void *user_data)
   gcc_jit_field *field_m_unsigned_long_long =
     CREATE_FIELD (GCC_JIT_TYPE_UNSIGNED_LONG_LONG, "m_unsigned_long_long");
 
+  gcc_jit_field *field_m_u8 =
+    CREATE_FIELD (GCC_JIT_TYPE_UINT8_T, "m_u8");
+  gcc_jit_field *field_m_u16 =
+    CREATE_FIELD (GCC_JIT_TYPE_UINT16_T, "m_u16");
+  gcc_jit_field *field_m_u32 =
+    CREATE_FIELD (GCC_JIT_TYPE_UINT32_T, "m_u32");
+  gcc_jit_field *field_m_u64 =
+    CREATE_FIELD (GCC_JIT_TYPE_UINT64_T, "m_u64");
+  gcc_jit_field *field_m_u128 =
+    CREATE_FIELD (GCC_JIT_TYPE_UINT128_T, "m_u128");
+
+  gcc_jit_field *field_m_i8 =
+    CREATE_FIELD (GCC_JIT_TYPE_INT8_T, "m_i8");
+  gcc_jit_field *field_m_i16 =
+    CREATE_FIELD (GCC_JIT_TYPE_INT16_T, "m_i16");
+  gcc_jit_field *field_m_i32 =
+    CREATE_FIELD (GCC_JIT_TYPE_INT32_T, "m_i32");
+  gcc_jit_field *field_m_i64 =
+    CREATE_FIELD (GCC_JIT_TYPE_INT64_T, "m_i64");
+  gcc_jit_field *field_m_i128 =
+    CREATE_FIELD (GCC_JIT_TYPE_INT128_T, "m_i128");
+
   /* Signed int type with sizeof (int): */
   gcc_jit_type *sized_int_type =
     gcc_jit_context_get_int_type (ctxt, sizeof (int), 1);
@@ -147,6 +182,18 @@ create_code (gcc_jit_context *ctxt, void *user_data)
     field_m_long_long,
     field_m_unsigned_long_long,
 
+    field_m_u8,
+    field_m_u16,
+    field_m_u32,
+    field_m_u64,
+    field_m_u128,
+
+    field_m_i8,
+    field_m_i16,
+    field_m_i32,
+    field_m_i64,
+    field_m_i128,
+
     field_m_sized_int_type,
 
     field_m_float,
@@ -266,6 +313,58 @@ create_code (gcc_jit_context *ctxt, void *user_data)
       gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_UNSIGNED_LONG_LONG),
       123456789))
 
+  ASSIGN(field_m_u8,
+    gcc_jit_context_new_rvalue_from_int (
+      ctxt,
+      gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_UINT8_T),
+      123))
+  ASSIGN(field_m_u16,
+    gcc_jit_context_new_rvalue_from_int (
+      ctxt,
+      gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_UINT16_T),
+      12345))
+  ASSIGN(field_m_u32,
+    gcc_jit_context_new_rvalue_from_int (
+      ctxt,
+      gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_UINT32_T),
+      123456789))
+  ASSIGN(field_m_u64,
+    gcc_jit_context_new_rvalue_from_int (
+      ctxt,
+      gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_UINT64_T),
+      123456789))
+  ASSIGN(field_m_u128,
+    gcc_jit_context_new_rvalue_from_int (
+      ctxt,
+      gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_UINT128_T),
+      123456789))
+
+  ASSIGN(field_m_i8,
+    gcc_jit_context_new_rvalue_from_int (
+      ctxt,
+      gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_INT8_T),
+      -1))
+  ASSIGN(field_m_i16,
+    gcc_jit_context_new_rvalue_from_int (
+      ctxt,
+      gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_INT16_T),
+      -2))
+  ASSIGN(field_m_i32,
+    gcc_jit_context_new_rvalue_from_int (
+      ctxt,
+      gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_INT32_T),
+      -3))
+  ASSIGN(field_m_i64,
+    gcc_jit_context_new_rvalue_from_int (
+      ctxt,
+      gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_INT64_T),
+      -4))
+  ASSIGN(field_m_i128,
+    gcc_jit_context_new_rvalue_from_int (
+      ctxt,
+      gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_INT128_T),
+      -5))
+
   ASSIGN(field_m_sized_int_type,
     gcc_jit_context_new_rvalue_from_int (
       ctxt,
@@ -347,6 +446,18 @@ verify_code (gcc_jit_context *ctxt, gcc_jit_result *result)
   CHECK_VALUE (z.m_long_long, -42);
   CHECK_VALUE (z.m_unsigned_long_long, 123456789);
 
+  CHECK_VALUE (z.m_u8, 123);
+  CHECK_VALUE (z.m_u16, 12345);
+  CHECK_VALUE (z.m_u32, 123456789);
+  CHECK_VALUE (z.m_u64, 123456789);
+  CHECK_VALUE (z.m_u128, 123456789);
+
+  CHECK_VALUE (z.m_i8, -1);
+  CHECK_VALUE (z.m_i16, -2);
+  CHECK_VALUE (z.m_i32, -3);
+  CHECK_VALUE (z.m_i64, -4);
+  CHECK_VALUE (z.m_i128, -5);
+
   CHECK_VALUE (z.m_sized_int_type, 500);
 
   CHECK_VALUE (z.m_float, 3.141f);
-- 
2.31.1


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

* Re: [PATCH] libgccjit: Add support for sized integer types, including 128-bit integers [PR95325]
  2021-05-18 12:23 [PATCH] libgccjit: Add support for sized integer types, including 128-bit integers [PR95325] Antoni Boucher
  2021-05-18 12:36 ` Antoni Boucher
@ 2021-05-18 12:53 ` Jakub Jelinek
  2021-05-20 19:25   ` David Malcolm
  1 sibling, 1 reply; 8+ messages in thread
From: Jakub Jelinek @ 2021-05-18 12:53 UTC (permalink / raw)
  To: Antoni Boucher; +Cc: jit, gcc-patches

On Tue, May 18, 2021 at 08:23:56AM -0400, Antoni Boucher via Gcc-patches wrote:
> Hello.
> This patch add support for sized integer types.
> Maybe it should check whether the size of a byte for the current
> platform is 8 bits and do other checks so that they're only available
> when it makes sense.
> What do you think?

Not a review, just a comment.  The 128-bit integral types are available
only on some targets, the test e.g. the C/C++ FE do for those is
targetm.scalar_mode_supported_p (TImode)
and so even libgccjit shouldn't provide those types unconditionally.
Similarly for the tests (though it could be guarded with e.g
#ifdef __SIZEOF_INT128__
in that case).
Also, while currently all in tree targets have BITS_PER_UNIT 8 and
therefore QImode is 8-bit, HImode 16-bit, SImode 32-bit and DImode 64-bit,
in the past and maybe in he future there can be targets that could have
e.g. 16-bit or 32-bit QImode and then there wouldn't be any uint8_t/int8_t
and int16_t would be intQImode_type_node etc.
  uint16_type_node = make_or_reuse_type (16, 1);
  uint32_type_node = make_or_reuse_type (32, 1);
  uint64_type_node = make_or_reuse_type (64, 1);
  if (targetm.scalar_mode_supported_p (TImode))
    uint128_type_node = make_or_reuse_type (128, 1);
are always with the given precisions, perhaps jit should use
signed_type_for (uint16_type_node) etc.?

	Jakub


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

* Re: [PATCH] libgccjit: Add support for sized integer types, including 128-bit integers [PR95325]
  2021-05-18 12:53 ` Jakub Jelinek
@ 2021-05-20 19:25   ` David Malcolm
  2022-01-04  3:13     ` Antoni Boucher
  2022-01-21 16:22     ` Antoni Boucher
  0 siblings, 2 replies; 8+ messages in thread
From: David Malcolm @ 2021-05-20 19:25 UTC (permalink / raw)
  To: Jakub Jelinek, Antoni Boucher; +Cc: jit, gcc-patches

On Tue, 2021-05-18 at 14:53 +0200, Jakub Jelinek via Jit wrote:
> On Tue, May 18, 2021 at 08:23:56AM -0400, Antoni Boucher via Gcc-
> patches wrote:
> > Hello.
> > This patch add support for sized integer types.
> > Maybe it should check whether the size of a byte for the current
> > platform is 8 bits and do other checks so that they're only available
> > when it makes sense.
> > What do you think?
> 
> Not a review, just a comment.  The 128-bit integral types are available
> only on some targets, the test e.g. the C/C++ FE do for those is
> targetm.scalar_mode_supported_p (TImode)
> and so even libgccjit shouldn't provide those types unconditionally.
> Similarly for the tests (though it could be guarded with e.g
> #ifdef __SIZEOF_INT128__
> in that case).
> Also, while currently all in tree targets have BITS_PER_UNIT 8 and
> therefore QImode is 8-bit, HImode 16-bit, SImode 32-bit and DImode 64-
> bit,
> in the past and maybe in he future there can be targets that could have
> e.g. 16-bit or 32-bit QImode and then there wouldn't be any
> uint8_t/int8_t
> and int16_t would be intQImode_type_node etc.
>   uint16_type_node = make_or_reuse_type (16, 1);
>   uint32_type_node = make_or_reuse_type (32, 1);
>   uint64_type_node = make_or_reuse_type (64, 1);
>   if (targetm.scalar_mode_supported_p (TImode))
>     uint128_type_node = make_or_reuse_type (128, 1);
> are always with the given precisions, perhaps jit should use
> signed_type_for (uint16_type_node) etc.?

I seem to have mislaid Antoni's original email (sorry), so I'll reply
to Jakub's.

> 2021-05-18  Antoni Boucher  <bouanto@zoho.com>
> 
>     gcc/jit/
>             PR target/95325
>             * jit-playback.c: Add support for the sized integer types.
>             * jit-recording.c: Add support for the sized integer types.
>             * libgccjit.h (GCC_JIT_TYPE_UINT8_T, GCC_JIT_TYPE_UINT16_T,
>             GCC_JIT_TYPE_UINT32_T, GCC_JIT_TYPE_UINT64_T,
>             GCC_JIT_TYPE_UINT128_T, GCC_JIT_TYPE_INT8_T, GCC_JIT_TYPE_INT16_T,
>             GCC_JIT_TYPE_INT32_T, GCC_JIT_TYPE_INT64_T, GCC_JIT_TYPE_INT128_T):
>             New enum variants for gcc_jit_types.
>     gcc/testsuite/
>             PR target/95325
>             * jit.dg/test-types.c: Add tests for sized integer types.

First a high-level question, why not use (or extend)
gcc_jit_context_get_int_type instead?

Do we really need to extend enum gcc_jit_types?  Is this a quality-of-
life thing for users of the library?

That said, recording::context::get_int_type is currently a bit of a
hack, and maybe could probably be improved by using the new enum values
the patch adds.

IIRC, libgccjit.c does type-checking by comparing recording::type
pointer values; does this patch gives us multiple equivalent types that
ought to compare as equal?

If a user gets a type via GCC_JIT_TYPE_INT and gets "another" type via
GCC_JIT_TYPE_INT32_T and they happen to be the same on the current
target, should libgccjit complain if you use "int" when you meant
"int32_t", or accept it?

Various comments inline below...

> diff --git a/gcc/jit/jit-playback.c b/gcc/jit/jit-playback.c
> index c6136301243..40630aa1ab8 100644
> --- a/gcc/jit/jit-playback.c
> +++ b/gcc/jit/jit-playback.c
> @@ -193,6 +193,27 @@ get_tree_node_for_type (enum gcc_jit_types type_)
>      case GCC_JIT_TYPE_UNSIGNED_INT:
>        return unsigned_type_node;
>  
> +    case GCC_JIT_TYPE_UINT8_T:
> +      return unsigned_intQI_type_node;
> +    case GCC_JIT_TYPE_UINT16_T:
> +      return uint16_type_node;
> +    case GCC_JIT_TYPE_UINT32_T:
> +      return uint32_type_node;
> +    case GCC_JIT_TYPE_UINT64_T:
> +      return uint64_type_node;
> +    case GCC_JIT_TYPE_UINT128_T:
> +      return uint128_type_node;
> +    case GCC_JIT_TYPE_INT8_T:
> +      return intQI_type_node;
> +    case GCC_JIT_TYPE_INT16_T:
> +      return intHI_type_node;
> +    case GCC_JIT_TYPE_INT32_T:
> +      return intSI_type_node;
> +    case GCC_JIT_TYPE_INT64_T:
> +      return intDI_type_node;
> +    case GCC_JIT_TYPE_INT128_T:
> +      return intTI_type_node;
> +

Jakub has already commented that 128 bit types might not be available.

Ideally we'd report that they're not available as soon as the user
tries to use them, in gcc_jit_context_get_type, but unfortunately it
looks like the test requires us to use targetm.scalar_mode_supported_p,
and that requires us to hold the jit mutex and thus be at playback
time.

So I think get_tree_node_for_type should take a context, and add an
error on the context if there's a failure, returning NULL. 
playback::context::get_type is the only caller currently and has
handling for an unrecognized value, so I think that logic needs to be
moved to get_tree_node_for_type so that the user can distinguish
between unrecognized types versus types that are unsupported on this
target.


> diff --git a/gcc/jit/jit-recording.c b/gcc/jit/jit-recording.c
> index 117ff70114c..b67ae8bfb78 100644
> --- a/gcc/jit/jit-recording.c
> +++ b/gcc/jit/jit-recording.c
> @@ -2247,6 +2247,18 @@ recording::memento_of_get_type::get_size ()
>      case GCC_JIT_TYPE_UNSIGNED_LONG_LONG:
>        size = LONG_LONG_TYPE_SIZE;
>        break;
> +    case GCC_JIT_TYPE_UINT8_T:
> +    case GCC_JIT_TYPE_UINT16_T:
> +    case GCC_JIT_TYPE_UINT32_T:
> +    case GCC_JIT_TYPE_UINT64_T:
> +    case GCC_JIT_TYPE_UINT128_T:
> +    case GCC_JIT_TYPE_INT8_T:
> +    case GCC_JIT_TYPE_INT16_T:
> +    case GCC_JIT_TYPE_INT32_T:
> +    case GCC_JIT_TYPE_INT64_T:
> +    case GCC_JIT_TYPE_INT128_T:
> +      size = 128;
> +      break;

This gives 128 bits as the size for all of these types, which seems
wrong.

>      case GCC_JIT_TYPE_FLOAT:
>        size = FLOAT_TYPE_SIZE;
>        break;
>      case GCC_JIT_TYPE_FLOAT:

> diff --git a/gcc/jit/libgccjit.h b/gcc/jit/libgccjit.h
> index 5c722c2c57f..5d88033a2ab 100644
> --- a/gcc/jit/libgccjit.h
> +++ b/gcc/jit/libgccjit.h
> @@ -548,6 +548,17 @@ enum gcc_jit_types
>    GCC_JIT_TYPE_LONG_LONG, /* signed */
>    GCC_JIT_TYPE_UNSIGNED_LONG_LONG,
>  
> +  GCC_JIT_TYPE_UINT8_T,
> +  GCC_JIT_TYPE_UINT16_T,
> +  GCC_JIT_TYPE_UINT32_T,
> +  GCC_JIT_TYPE_UINT64_T,
> +  GCC_JIT_TYPE_UINT128_T,
> +  GCC_JIT_TYPE_INT8_T,
> +  GCC_JIT_TYPE_INT16_T,
> +  GCC_JIT_TYPE_INT32_T,
> +  GCC_JIT_TYPE_INT64_T,
> +  GCC_JIT_TYPE_INT128_T,
> +
>    /* Floating-point types  */
>  
>    GCC_JIT_TYPE_FLOAT,

The patch adds the new enum values between existing values of enum
gcc_jit_types, effectively changing the ABI, since e.g. the numerical
value of GCC_JIT_TYPE_FLOAT changes with this, and there's no way of
telling which enum values a binary linked against libgccjit.so is going
to supply when it calls into libgccjit.

If we're going to extend the enum, the new values need to be added to
the end, extending the ABI rather than changing it.

I don't think the patch provides a way to detect that the client code
is using the new ABI and thus mark it in the metadata.  I'm not sure
how to do that.

> diff --git a/gcc/testsuite/jit.dg/test-types.c b/gcc/testsuite/jit.dg/test-types.c
> index 8debcd7eb82..9c66284f193 100644
> --- a/gcc/testsuite/jit.dg/test-types.c
> +++ b/gcc/testsuite/jit.dg/test-types.c

[...snip...]

The tests seem reasonable, but as noted by Jakub the 128-bit support
needs to be conditionalized.

Hope this is constructive
Dave


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

* Re: [PATCH] libgccjit: Add support for sized integer types, including 128-bit integers [PR95325]
  2021-05-20 19:25   ` David Malcolm
@ 2022-01-04  3:13     ` Antoni Boucher
  2022-01-21 16:22     ` Antoni Boucher
  1 sibling, 0 replies; 8+ messages in thread
From: Antoni Boucher @ 2022-01-04  3:13 UTC (permalink / raw)
  To: David Malcolm; +Cc: jit, gcc-patches

Hi, David!

One question below as I'm still not done with using this patch in
rustc_codegen_gcc.

Le jeudi 20 mai 2021 à 15:25 -0400, David Malcolm a écrit :
> On Tue, 2021-05-18 at 14:53 +0200, Jakub Jelinek via Jit wrote:
> > On Tue, May 18, 2021 at 08:23:56AM -0400, Antoni Boucher via Gcc-
> > patches wrote:
> > > Hello.
> > > This patch add support for sized integer types.
> > > Maybe it should check whether the size of a byte for the current
> > > platform is 8 bits and do other checks so that they're only
> > > available
> > > when it makes sense.
> > > What do you think?
> > 
> > Not a review, just a comment.  The 128-bit integral types are
> > available
> > only on some targets, the test e.g. the C/C++ FE do for those is
> > targetm.scalar_mode_supported_p (TImode)
> > and so even libgccjit shouldn't provide those types
> > unconditionally.
> > Similarly for the tests (though it could be guarded with e.g
> > #ifdef __SIZEOF_INT128__
> > in that case).
> > Also, while currently all in tree targets have BITS_PER_UNIT 8 and
> > therefore QImode is 8-bit, HImode 16-bit, SImode 32-bit and DImode
> > 64-
> > bit,
> > in the past and maybe in he future there can be targets that could
> > have
> > e.g. 16-bit or 32-bit QImode and then there wouldn't be any
> > uint8_t/int8_t
> > and int16_t would be intQImode_type_node etc.
> >   uint16_type_node = make_or_reuse_type (16, 1);
> >   uint32_type_node = make_or_reuse_type (32, 1);
> >   uint64_type_node = make_or_reuse_type (64, 1);
> >   if (targetm.scalar_mode_supported_p (TImode))
> >     uint128_type_node = make_or_reuse_type (128, 1);
> > are always with the given precisions, perhaps jit should use
> > signed_type_for (uint16_type_node) etc.?
> 
> I seem to have mislaid Antoni's original email (sorry), so I'll reply
> to Jakub's.
> 
> > 2021-05-18  Antoni Boucher  <bouanto@zoho.com>
> > 
> >     gcc/jit/
> >             PR target/95325
> >             * jit-playback.c: Add support for the sized integer
> > types.
> >             * jit-recording.c: Add support for the sized integer
> > types.
> >             * libgccjit.h (GCC_JIT_TYPE_UINT8_T,
> > GCC_JIT_TYPE_UINT16_T,
> >             GCC_JIT_TYPE_UINT32_T, GCC_JIT_TYPE_UINT64_T,
> >             GCC_JIT_TYPE_UINT128_T, GCC_JIT_TYPE_INT8_T,
> > GCC_JIT_TYPE_INT16_T,
> >             GCC_JIT_TYPE_INT32_T, GCC_JIT_TYPE_INT64_T,
> > GCC_JIT_TYPE_INT128_T):
> >             New enum variants for gcc_jit_types.
> >     gcc/testsuite/
> >             PR target/95325
> >             * jit.dg/test-types.c: Add tests for sized integer
> > types.
> 
> First a high-level question, why not use (or extend)
> gcc_jit_context_get_int_type instead?
> 
> Do we really need to extend enum gcc_jit_types?  Is this a quality-
> of-
> life thing for users of the library?
> 
> That said, recording::context::get_int_type is currently a bit of a
> hack, and maybe could probably be improved by using the new enum
> values
> the patch adds.
> 
> IIRC, libgccjit.c does type-checking by comparing recording::type
> pointer values; does this patch gives us multiple equivalent types
> that
> ought to compare as equal?
> 
> If a user gets a type via GCC_JIT_TYPE_INT and gets "another" type
> via
> GCC_JIT_TYPE_INT32_T and they happen to be the same on the current
> target, should libgccjit complain if you use "int" when you meant
> "int32_t", or accept it?
> 
> Various comments inline below...
> 
> > diff --git a/gcc/jit/jit-playback.c b/gcc/jit/jit-playback.c
> > index c6136301243..40630aa1ab8 100644
> > --- a/gcc/jit/jit-playback.c
> > +++ b/gcc/jit/jit-playback.c
> > @@ -193,6 +193,27 @@ get_tree_node_for_type (enum gcc_jit_types
> > type_)
> >      case GCC_JIT_TYPE_UNSIGNED_INT:
> >        return unsigned_type_node;
> >  
> > +    case GCC_JIT_TYPE_UINT8_T:
> > +      return unsigned_intQI_type_node;
> > +    case GCC_JIT_TYPE_UINT16_T:
> > +      return uint16_type_node;
> > +    case GCC_JIT_TYPE_UINT32_T:
> > +      return uint32_type_node;
> > +    case GCC_JIT_TYPE_UINT64_T:
> > +      return uint64_type_node;
> > +    case GCC_JIT_TYPE_UINT128_T:
> > +      return uint128_type_node;
> > +    case GCC_JIT_TYPE_INT8_T:
> > +      return intQI_type_node;
> > +    case GCC_JIT_TYPE_INT16_T:
> > +      return intHI_type_node;
> > +    case GCC_JIT_TYPE_INT32_T:
> > +      return intSI_type_node;
> > +    case GCC_JIT_TYPE_INT64_T:
> > +      return intDI_type_node;
> > +    case GCC_JIT_TYPE_INT128_T:
> > +      return intTI_type_node;
> > +
> 
> Jakub has already commented that 128 bit types might not be
> available.
> 
> Ideally we'd report that they're not available as soon as the user
> tries to use them, in gcc_jit_context_get_type, but unfortunately it
> looks like the test requires us to use
> targetm.scalar_mode_supported_p,
> and that requires us to hold the jit mutex and thus be at playback
> time.

I'd need a way to check if 128-bit integers are supported and if not,
use something else.
The fact that this check is only available at playback makes this
tricky.
I tried the hack of creating a context, creating a 128-bit integer type
and checking for errors, but even this won't work, because creating a
new context will call initialize_sizetypes, which will overwrite the
types and cause some issues later, for instance having
VIEW_CONVERT_EXPR fails some checks
(https://github.com/gcc-mirror/gcc/blob/master/gcc/tree-cfg.c#L3203)
because the tree for the sizes will be different (even though the value
of those trees is the same).

Any thoughts on how best to solve this issue?

> 
> So I think get_tree_node_for_type should take a context, and add an
> error on the context if there's a failure, returning NULL. 
> playback::context::get_type is the only caller currently and has
> handling for an unrecognized value, so I think that logic needs to be
> moved to get_tree_node_for_type so that the user can distinguish
> between unrecognized types versus types that are unsupported on this
> target.
> 
> 
> > diff --git a/gcc/jit/jit-recording.c b/gcc/jit/jit-recording.c
> > index 117ff70114c..b67ae8bfb78 100644
> > --- a/gcc/jit/jit-recording.c
> > +++ b/gcc/jit/jit-recording.c
> > @@ -2247,6 +2247,18 @@ recording::memento_of_get_type::get_size ()
> >      case GCC_JIT_TYPE_UNSIGNED_LONG_LONG:
> >        size = LONG_LONG_TYPE_SIZE;
> >        break;
> > +    case GCC_JIT_TYPE_UINT8_T:
> > +    case GCC_JIT_TYPE_UINT16_T:
> > +    case GCC_JIT_TYPE_UINT32_T:
> > +    case GCC_JIT_TYPE_UINT64_T:
> > +    case GCC_JIT_TYPE_UINT128_T:
> > +    case GCC_JIT_TYPE_INT8_T:
> > +    case GCC_JIT_TYPE_INT16_T:
> > +    case GCC_JIT_TYPE_INT32_T:
> > +    case GCC_JIT_TYPE_INT64_T:
> > +    case GCC_JIT_TYPE_INT128_T:
> > +      size = 128;
> > +      break;
> 
> This gives 128 bits as the size for all of these types, which seems
> wrong.
> 
> >      case GCC_JIT_TYPE_FLOAT:
> >        size = FLOAT_TYPE_SIZE;
> >        break;
> >      case GCC_JIT_TYPE_FLOAT:
> 
> > diff --git a/gcc/jit/libgccjit.h b/gcc/jit/libgccjit.h
> > index 5c722c2c57f..5d88033a2ab 100644
> > --- a/gcc/jit/libgccjit.h
> > +++ b/gcc/jit/libgccjit.h
> > @@ -548,6 +548,17 @@ enum gcc_jit_types
> >    GCC_JIT_TYPE_LONG_LONG, /* signed */
> >    GCC_JIT_TYPE_UNSIGNED_LONG_LONG,
> >  
> > +  GCC_JIT_TYPE_UINT8_T,
> > +  GCC_JIT_TYPE_UINT16_T,
> > +  GCC_JIT_TYPE_UINT32_T,
> > +  GCC_JIT_TYPE_UINT64_T,
> > +  GCC_JIT_TYPE_UINT128_T,
> > +  GCC_JIT_TYPE_INT8_T,
> > +  GCC_JIT_TYPE_INT16_T,
> > +  GCC_JIT_TYPE_INT32_T,
> > +  GCC_JIT_TYPE_INT64_T,
> > +  GCC_JIT_TYPE_INT128_T,
> > +
> >    /* Floating-point types  */
> >  
> >    GCC_JIT_TYPE_FLOAT,
> 
> The patch adds the new enum values between existing values of enum
> gcc_jit_types, effectively changing the ABI, since e.g. the numerical
> value of GCC_JIT_TYPE_FLOAT changes with this, and there's no way of
> telling which enum values a binary linked against libgccjit.so is
> going
> to supply when it calls into libgccjit.
> 
> If we're going to extend the enum, the new values need to be added to
> the end, extending the ABI rather than changing it.
> 
> I don't think the patch provides a way to detect that the client code
> is using the new ABI and thus mark it in the metadata.  I'm not sure
> how to do that.
> 
> > diff --git a/gcc/testsuite/jit.dg/test-types.c
> > b/gcc/testsuite/jit.dg/test-types.c
> > index 8debcd7eb82..9c66284f193 100644
> > --- a/gcc/testsuite/jit.dg/test-types.c
> > +++ b/gcc/testsuite/jit.dg/test-types.c
> 
> [...snip...]
> 
> The tests seem reasonable, but as noted by Jakub the 128-bit support
> needs to be conditionalized.
> 
> Hope this is constructive
> Dave
> 


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

* Re: [PATCH] libgccjit: Add support for sized integer types, including 128-bit integers [PR95325]
  2021-05-20 19:25   ` David Malcolm
  2022-01-04  3:13     ` Antoni Boucher
@ 2022-01-21 16:22     ` Antoni Boucher
  2022-04-08 20:29       ` Antoni Boucher
  1 sibling, 1 reply; 8+ messages in thread
From: Antoni Boucher @ 2022-01-21 16:22 UTC (permalink / raw)
  To: David Malcolm, Jakub Jelinek; +Cc: jit, gcc-patches

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

David: this is the email I was talking about in my other email.
Here's the updated patch.

By the way, I find the usage of NUM_GCC_JIT_TYPES brittle. Would it be
better to switch to a new enum value for that instead?

See comments below.

Le jeudi 20 mai 2021 à 15:25 -0400, David Malcolm a écrit :
> On Tue, 2021-05-18 at 14:53 +0200, Jakub Jelinek via Jit wrote:
> > On Tue, May 18, 2021 at 08:23:56AM -0400, Antoni Boucher via Gcc-
> > patches wrote:
> > > Hello.
> > > This patch add support for sized integer types.
> > > Maybe it should check whether the size of a byte for the current
> > > platform is 8 bits and do other checks so that they're only
> > > available
> > > when it makes sense.
> > > What do you think?
> > 
> > Not a review, just a comment.  The 128-bit integral types are
> > available
> > only on some targets, the test e.g. the C/C++ FE do for those is
> > targetm.scalar_mode_supported_p (TImode)
> > and so even libgccjit shouldn't provide those types
> > unconditionally.
> > Similarly for the tests (though it could be guarded with e.g
> > #ifdef __SIZEOF_INT128__
> > in that case).
> > Also, while currently all in tree targets have BITS_PER_UNIT 8 and
> > therefore QImode is 8-bit, HImode 16-bit, SImode 32-bit and DImode
> > 64-
> > bit,
> > in the past and maybe in he future there can be targets that could
> > have
> > e.g. 16-bit or 32-bit QImode and then there wouldn't be any
> > uint8_t/int8_t
> > and int16_t would be intQImode_type_node etc.
> >   uint16_type_node = make_or_reuse_type (16, 1);
> >   uint32_type_node = make_or_reuse_type (32, 1);
> >   uint64_type_node = make_or_reuse_type (64, 1);
> >   if (targetm.scalar_mode_supported_p (TImode))
> >     uint128_type_node = make_or_reuse_type (128, 1);
> > are always with the given precisions, perhaps jit should use
> > signed_type_for (uint16_type_node) etc.?
> 
> I seem to have mislaid Antoni's original email (sorry), so I'll reply
> to Jakub's.
> 
> > 2021-05-18  Antoni Boucher  <bouanto@zoho.com>
> > 
> >     gcc/jit/
> >             PR target/95325
> >             * jit-playback.c: Add support for the sized integer
> > types.
> >             * jit-recording.c: Add support for the sized integer
> > types.
> >             * libgccjit.h (GCC_JIT_TYPE_UINT8_T,
> > GCC_JIT_TYPE_UINT16_T,
> >             GCC_JIT_TYPE_UINT32_T, GCC_JIT_TYPE_UINT64_T,
> >             GCC_JIT_TYPE_UINT128_T, GCC_JIT_TYPE_INT8_T,
> > GCC_JIT_TYPE_INT16_T,
> >             GCC_JIT_TYPE_INT32_T, GCC_JIT_TYPE_INT64_T,
> > GCC_JIT_TYPE_INT128_T):
> >             New enum variants for gcc_jit_types.
> >     gcc/testsuite/
> >             PR target/95325
> >             * jit.dg/test-types.c: Add tests for sized integer
> > types.
> 
> First a high-level question, why not use (or extend)
> gcc_jit_context_get_int_type instead?

If I remember correctly, I believe I had some issues with this
function, like having it return sometimes long long, and other times
long for the same size. Maybe that was an issue with a global variable
not cleaned up.

> 
> Do we really need to extend enum gcc_jit_types?  Is this a quality-
> of-
> life thing for users of the library?
> 
> That said, recording::context::get_int_type is currently a bit of a
> hack, and maybe could probably be improved by using the new enum
> values
> the patch adds.
> 
> IIRC, libgccjit.c does type-checking by comparing recording::type
> pointer values; does this patch gives us multiple equivalent types
> that
> ought to compare as equal?
> 
> If a user gets a type via GCC_JIT_TYPE_INT and gets "another" type
> via
> GCC_JIT_TYPE_INT32_T and they happen to be the same on the current
> target, should libgccjit complain if you use "int" when you meant
> "int32_t", or accept it?

I updated the function compatible_types to make them compare as equal.
I believe that it's not used everywhere though, so a cast will be
necessary in some cases.

> 
> Various comments inline below...
> 
> > diff --git a/gcc/jit/jit-playback.c b/gcc/jit/jit-playback.c
> > index c6136301243..40630aa1ab8 100644
> > --- a/gcc/jit/jit-playback.c
> > +++ b/gcc/jit/jit-playback.c
> > @@ -193,6 +193,27 @@ get_tree_node_for_type (enum gcc_jit_types
> > type_)
> >      case GCC_JIT_TYPE_UNSIGNED_INT:
> >        return unsigned_type_node;
> >  
> > +    case GCC_JIT_TYPE_UINT8_T:
> > +      return unsigned_intQI_type_node;
> > +    case GCC_JIT_TYPE_UINT16_T:
> > +      return uint16_type_node;
> > +    case GCC_JIT_TYPE_UINT32_T:
> > +      return uint32_type_node;
> > +    case GCC_JIT_TYPE_UINT64_T:
> > +      return uint64_type_node;
> > +    case GCC_JIT_TYPE_UINT128_T:
> > +      return uint128_type_node;
> > +    case GCC_JIT_TYPE_INT8_T:
> > +      return intQI_type_node;
> > +    case GCC_JIT_TYPE_INT16_T:
> > +      return intHI_type_node;
> > +    case GCC_JIT_TYPE_INT32_T:
> > +      return intSI_type_node;
> > +    case GCC_JIT_TYPE_INT64_T:
> > +      return intDI_type_node;
> > +    case GCC_JIT_TYPE_INT128_T:
> > +      return intTI_type_node;
> > +
> 
> Jakub has already commented that 128 bit types might not be
> available.
> 
> Ideally we'd report that they're not available as soon as the user
> tries to use them, in gcc_jit_context_get_type, but unfortunately it
> looks like the test requires us to use
> targetm.scalar_mode_supported_p,
> and that requires us to hold the jit mutex and thus be at playback
> time.
> 
> So I think get_tree_node_for_type should take a context, and add an
> error on the context if there's a failure, returning NULL. 
> playback::context::get_type is the only caller currently and has
> handling for an unrecognized value, so I think that logic needs to be
> moved to get_tree_node_for_type so that the user can distinguish
> between unrecognized types versus types that are unsupported on this
> target.
> 
> 
> > diff --git a/gcc/jit/jit-recording.c b/gcc/jit/jit-recording.c
> > index 117ff70114c..b67ae8bfb78 100644
> > --- a/gcc/jit/jit-recording.c
> > +++ b/gcc/jit/jit-recording.c
> > @@ -2247,6 +2247,18 @@ recording::memento_of_get_type::get_size ()
> >      case GCC_JIT_TYPE_UNSIGNED_LONG_LONG:
> >        size = LONG_LONG_TYPE_SIZE;
> >        break;
> > +    case GCC_JIT_TYPE_UINT8_T:
> > +    case GCC_JIT_TYPE_UINT16_T:
> > +    case GCC_JIT_TYPE_UINT32_T:
> > +    case GCC_JIT_TYPE_UINT64_T:
> > +    case GCC_JIT_TYPE_UINT128_T:
> > +    case GCC_JIT_TYPE_INT8_T:
> > +    case GCC_JIT_TYPE_INT16_T:
> > +    case GCC_JIT_TYPE_INT32_T:
> > +    case GCC_JIT_TYPE_INT64_T:
> > +    case GCC_JIT_TYPE_INT128_T:
> > +      size = 128;
> > +      break;
> 
> This gives 128 bits as the size for all of these types, which seems
> wrong.
> 
> >      case GCC_JIT_TYPE_FLOAT:
> >        size = FLOAT_TYPE_SIZE;
> >        break;
> >      case GCC_JIT_TYPE_FLOAT:
> 
> > diff --git a/gcc/jit/libgccjit.h b/gcc/jit/libgccjit.h
> > index 5c722c2c57f..5d88033a2ab 100644
> > --- a/gcc/jit/libgccjit.h
> > +++ b/gcc/jit/libgccjit.h
> > @@ -548,6 +548,17 @@ enum gcc_jit_types
> >    GCC_JIT_TYPE_LONG_LONG, /* signed */
> >    GCC_JIT_TYPE_UNSIGNED_LONG_LONG,
> >  
> > +  GCC_JIT_TYPE_UINT8_T,
> > +  GCC_JIT_TYPE_UINT16_T,
> > +  GCC_JIT_TYPE_UINT32_T,
> > +  GCC_JIT_TYPE_UINT64_T,
> > +  GCC_JIT_TYPE_UINT128_T,
> > +  GCC_JIT_TYPE_INT8_T,
> > +  GCC_JIT_TYPE_INT16_T,
> > +  GCC_JIT_TYPE_INT32_T,
> > +  GCC_JIT_TYPE_INT64_T,
> > +  GCC_JIT_TYPE_INT128_T,
> > +
> >    /* Floating-point types  */
> >  
> >    GCC_JIT_TYPE_FLOAT,
> 
> The patch adds the new enum values between existing values of enum
> gcc_jit_types, effectively changing the ABI, since e.g. the numerical
> value of GCC_JIT_TYPE_FLOAT changes with this, and there's no way of
> telling which enum values a binary linked against libgccjit.so is
> going
> to supply when it calls into libgccjit.
> 
> If we're going to extend the enum, the new values need to be added to
> the end, extending the ABI rather than changing it.

Fixed.

> 
> I don't think the patch provides a way to detect that the client code
> is using the new ABI and thus mark it in the metadata.  I'm not sure
> how to do that.

Now this patch adds new functions. Does that solve this issue?

> 
> > diff --git a/gcc/testsuite/jit.dg/test-types.c
> > b/gcc/testsuite/jit.dg/test-types.c
> > index 8debcd7eb82..9c66284f193 100644
> > --- a/gcc/testsuite/jit.dg/test-types.c
> > +++ b/gcc/testsuite/jit.dg/test-types.c
> 
> [...snip...]
> 
> The tests seem reasonable, but as noted by Jakub the 128-bit support
> needs to be conditionalized.
> 
> Hope this is constructive
> Dave
> 


[-- Attachment #2: 0001-libgccjit-Add-support-for-sized-integer-types-includ.patch --]
[-- Type: text/x-patch, Size: 31099 bytes --]

From db8836d1e16e432b6f40a26549648f6477d491bc Mon Sep 17 00:00:00 2001
From: Antoni Boucher <bouanto@zoho.com>
Date: Mon, 10 May 2021 19:43:02 -0400
Subject: [PATCH] libgccjit: Add support for sized integer types, including
 128-bit integers [PR95325]

2022-01-19  Antoni Boucher  <bouanto@zoho.com>

gcc/jit/
	PR target/95325
	* docs/topics/compatibility.rst (LIBGCCJIT_ABI_20): New ABI tag.
	* docs/topics/types.rst: Add documentation for the new types
	GCC_JIT_TYPE_UINT8_T, GCC_JIT_TYPE_UINT16_T,
	GCC_JIT_TYPE_UINT32_T, GCC_JIT_TYPE_UINT64_T,
	GCC_JIT_TYPE_UINT128_T, GCC_JIT_TYPE_INT8_T, GCC_JIT_TYPE_INT16_T,
	GCC_JIT_TYPE_INT32_T, GCC_JIT_TYPE_INT64_T, GCC_JIT_TYPE_INT128_T and
	new functions (gcc_jit_compatible_types, gcc_jit_type_get_size).
	* jit-builtins.cc: Add support for BT_UINT128.
	* jit-common.h: Update the value of NUM_GCC_JIT_TYPES.
	* jit-playback.cc: Add support for the sized integer types.
	* jit-recording.cc: Add support for the sized integer types.
	* jit-recording.h: Add support for comparing integer types
	and new function (is_signed).
	* libgccjit.cc: Rename compatible_types to
	gcc_jit_compatible_types and new function (gcc_jit_type_get_size).
	* libgccjit.h: New enum variants for gcc_jit_types
	(GCC_JIT_TYPE_UINT8_T, GCC_JIT_TYPE_UINT16_T,
	GCC_JIT_TYPE_UINT32_T, GCC_JIT_TYPE_UINT64_T,
	GCC_JIT_TYPE_UINT128_T, GCC_JIT_TYPE_INT8_T,
	GCC_JIT_TYPE_INT16_T, GCC_JIT_TYPE_INT32_T,
	GCC_JIT_TYPE_INT64_T, GCC_JIT_TYPE_INT128_T) and new functions
	(gcc_jit_compatible_types, gcc_jit_type_get_size).
	libgccjit.map (LIBGCCJIT_ABI_20): New ABI tag.

gcc/testsuite/
	PR target/95325
	* jit.dg/test-types.c: Add tests for sized integer types.
---
 gcc/jit/docs/topics/compatibility.rst |  20 ++++
 gcc/jit/docs/topics/types.rst         |  41 ++++++++
 gcc/jit/jit-builtins.cc               |   1 +
 gcc/jit/jit-common.h                  |   2 +-
 gcc/jit/jit-playback.cc               |  37 ++++++-
 gcc/jit/jit-recording.cc              | 146 +++++++++++++++++++++++++-
 gcc/jit/jit-recording.h               |  16 +++
 gcc/jit/libgccjit.cc                  |  52 +++++----
 gcc/jit/libgccjit.h                   |  32 +++++-
 gcc/jit/libgccjit.map                 |   6 ++
 gcc/testsuite/jit.dg/test-types.c     | 131 +++++++++++++++++++++++
 11 files changed, 457 insertions(+), 27 deletions(-)

diff --git a/gcc/jit/docs/topics/compatibility.rst b/gcc/jit/docs/topics/compatibility.rst
index 16cebe31a10..73a17664698 100644
--- a/gcc/jit/docs/topics/compatibility.rst
+++ b/gcc/jit/docs/topics/compatibility.rst
@@ -302,3 +302,23 @@ thread-local storage model of a variable:
 section of a variable:
 
   * :func:`gcc_jit_lvalue_set_link_section`
+
+.. _LIBGCCJIT_ABI_20:
+
+``LIBGCCJIT_ABI_20``
+-----------------------
+``LIBGCCJIT_ABI_20`` covers the addition of sized integer types, including
+128-bit integers and helper functions for types:
+
+  * :func:`gcc_jit_compatible_types`
+  * :func:`gcc_jit_type_get_size`
+  * :c:macro:`GCC_JIT_TYPE_UINT8_T`
+  * :c:macro:`GCC_JIT_TYPE_UINT16_T`
+  * :c:macro:`GCC_JIT_TYPE_UINT32_T`
+  * :c:macro:`GCC_JIT_TYPE_UINT64_T`
+  * :c:macro:`GCC_JIT_TYPE_UINT128_T`
+  * :c:macro:`GCC_JIT_TYPE_INT8_T`
+  * :c:macro:`GCC_JIT_TYPE_INT16_T`
+  * :c:macro:`GCC_JIT_TYPE_INT32_T`
+  * :c:macro:`GCC_JIT_TYPE_INT64_T`
+  * :c:macro:`GCC_JIT_TYPE_INT128_T`
diff --git a/gcc/jit/docs/topics/types.rst b/gcc/jit/docs/topics/types.rst
index 9779ad26b6f..ededf49e149 100644
--- a/gcc/jit/docs/topics/types.rst
+++ b/gcc/jit/docs/topics/types.rst
@@ -76,6 +76,16 @@ Standard types
    :c:data:`GCC_JIT_TYPE_UNSIGNED_LONG`        C's ``unsigned long``
    :c:data:`GCC_JIT_TYPE_LONG_LONG`            C99's ``long long`` (signed)
    :c:data:`GCC_JIT_TYPE_UNSIGNED_LONG_LONG`   C99's ``unsigned long long``
+   :c:data:`GCC_JIT_TYPE_UINT8_T`              C99's ``uint8_t``
+   :c:data:`GCC_JIT_TYPE_UINT16_T`             C99's ``uint16_t``
+   :c:data:`GCC_JIT_TYPE_UINT32_T`             C99's ``uint32_t``
+   :c:data:`GCC_JIT_TYPE_UINT64_T`             C99's ``uint64_t``
+   :c:data:`GCC_JIT_TYPE_UINT128_T`            C99's ``__uint128_t``
+   :c:data:`GCC_JIT_TYPE_INT8_T`               C99's ``int8_t``
+   :c:data:`GCC_JIT_TYPE_INT16_T`              C99's ``int16_t``
+   :c:data:`GCC_JIT_TYPE_INT32_T`              C99's ``int32_t``
+   :c:data:`GCC_JIT_TYPE_INT64_T`              C99's ``int64_t``
+   :c:data:`GCC_JIT_TYPE_INT128_T`             C99's ``__int128_t``
    :c:data:`GCC_JIT_TYPE_FLOAT`
    :c:data:`GCC_JIT_TYPE_DOUBLE`
    :c:data:`GCC_JIT_TYPE_LONG_DOUBLE`
@@ -467,3 +477,34 @@ Reflection API
       #ifdef LIBGCCJIT_HAVE_REFLECTION
 
    .. type:: gcc_jit_case
+
+.. function::  int\
+               gcc_jit_compatible_types (gcc_jit_type *ltype,
+                                         gcc_jit_type *rtype)
+
+     Return non-zero if the two types are compatible. For instance,
+     if :c:data:`GCC_JIT_TYPE_UINT64_T` and :c:data:`GCC_JIT_TYPE_UNSIGNED_LONG`
+     are the same size on the target, this will return non-zero.
+     The parameters ``ltype`` and ``rtype`` must be non-NULL.
+     Return 0 on errors.
+
+   This entrypoint was added in :ref:`LIBGCCJIT_ABI_20`; you can test for
+   its presence using
+
+   .. code-block:: c
+
+      #ifdef LIBGCCJIT_HAVE_SIZED_INTEGERS
+
+.. function::  ssize_t\
+               gcc_jit_type_get_size (gcc_jit_type *type)
+
+     Return the size of a type, in bytes. It only works on integer types for now.
+     The parameter ``type`` must be non-NULL.
+     Return -1 on errors.
+
+   This entrypoint was added in :ref:`LIBGCCJIT_ABI_20`; you can test for
+   its presence using
+
+   .. code-block:: c
+
+      #ifdef LIBGCCJIT_HAVE_SIZED_INTEGERS
diff --git a/gcc/jit/jit-builtins.cc b/gcc/jit/jit-builtins.cc
index 71c38eb0948..b949b734332 100644
--- a/gcc/jit/jit-builtins.cc
+++ b/gcc/jit/jit-builtins.cc
@@ -483,6 +483,7 @@ builtins_manager::make_primitive_type (enum jit_builtin_type type_id)
     case BT_UINT16: return m_ctxt->get_int_type (2, false);
     case BT_UINT32: return m_ctxt->get_int_type (4, false);
     case BT_UINT64: return m_ctxt->get_int_type (8, false);
+    case BT_UINT128: return m_ctxt->get_int_type (16, false);
     // case BT_WORD:
     // case BT_UNWINDWORD:
     case BT_FLOAT: return m_ctxt->get_type (GCC_JIT_TYPE_FLOAT);
diff --git a/gcc/jit/jit-common.h b/gcc/jit/jit-common.h
index 1a8cd8bac7b..8c52ddf80e1 100644
--- a/gcc/jit/jit-common.h
+++ b/gcc/jit/jit-common.h
@@ -36,7 +36,7 @@ along with GCC; see the file COPYING3.  If not see
 #endif
 #endif
 
-const int NUM_GCC_JIT_TYPES = GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE + 1;
+const int NUM_GCC_JIT_TYPES = GCC_JIT_TYPE_INT128_T + 1;
 
 /* This comment is included by the docs.
 
diff --git a/gcc/jit/jit-playback.cc b/gcc/jit/jit-playback.cc
index d1835c79863..4683e862611 100644
--- a/gcc/jit/jit-playback.cc
+++ b/gcc/jit/jit-playback.cc
@@ -237,6 +237,36 @@ get_tree_node_for_type (enum gcc_jit_types type_)
     case GCC_JIT_TYPE_UNSIGNED_INT:
       return unsigned_type_node;
 
+    case GCC_JIT_TYPE_UINT8_T:
+      return unsigned_intQI_type_node;
+    case GCC_JIT_TYPE_UINT16_T:
+      return uint16_type_node;
+    case GCC_JIT_TYPE_UINT32_T:
+      return uint32_type_node;
+    case GCC_JIT_TYPE_UINT64_T:
+      return uint64_type_node;
+    case GCC_JIT_TYPE_UINT128_T:
+      if (targetm.scalar_mode_supported_p (TImode))
+        return uint128_type_node;
+
+      add_error (NULL, "gcc_jit_types value unsupported on this target: %i", type_);
+      return NULL;
+
+    case GCC_JIT_TYPE_INT8_T:
+      return intQI_type_node;
+    case GCC_JIT_TYPE_INT16_T:
+      return intHI_type_node;
+    case GCC_JIT_TYPE_INT32_T:
+      return intSI_type_node;
+    case GCC_JIT_TYPE_INT64_T:
+      return intDI_type_node;
+    case GCC_JIT_TYPE_INT128_T:
+      if (targetm.scalar_mode_supported_p (TImode))
+        return intTI_type_node;
+
+      add_error (NULL, "gcc_jit_types value unsupported on this target: %i", type_);
+      return NULL;
+
     case GCC_JIT_TYPE_LONG:
       return long_integer_type_node;
     case GCC_JIT_TYPE_UNSIGNED_LONG:
@@ -268,6 +298,8 @@ get_tree_node_for_type (enum gcc_jit_types type_)
       return complex_long_double_type_node;
     }
 
+  add_error (NULL, "unrecognized (enum gcc_jit_types) value: %i", type_);
+
   return NULL;
 }
 
@@ -280,10 +312,7 @@ get_type (enum gcc_jit_types type_)
 {
   tree type_node = get_tree_node_for_type (type_);
   if (type_node == NULL)
-    {
-      add_error (NULL, "unrecognized (enum gcc_jit_types) value: %i", type_);
-      return NULL;
-    }
+    return NULL;
 
   return new type (type_node);
 }
diff --git a/gcc/jit/jit-recording.cc b/gcc/jit/jit-recording.cc
index 1e3fadfacd7..4ffdad0665f 100644
--- a/gcc/jit/jit-recording.cc
+++ b/gcc/jit/jit-recording.cc
@@ -822,6 +822,10 @@ recording::context::get_int_type (int num_bytes, int is_signed)
     return get_type (is_signed
 		     ? GCC_JIT_TYPE_LONG_LONG
 		     : GCC_JIT_TYPE_UNSIGNED_LONG_LONG);
+  if (num_bits == 128)
+    return get_type (is_signed
+		     ? GCC_JIT_TYPE_INT128_T
+		     : GCC_JIT_TYPE_UINT128_T);
 
   /* Some other size, not corresponding to the C int types.  */
   /* To be written: support arbitrary other sizes, sharing by
@@ -2325,6 +2329,26 @@ recording::memento_of_get_type::get_size ()
     case GCC_JIT_TYPE_UNSIGNED_LONG_LONG:
       size = LONG_LONG_TYPE_SIZE;
       break;
+    case GCC_JIT_TYPE_UINT8_T:
+    case GCC_JIT_TYPE_INT8_T:
+      size = 8;
+      break;
+    case GCC_JIT_TYPE_UINT16_T:
+    case GCC_JIT_TYPE_INT16_T:
+      size = 16;
+      break;
+    case GCC_JIT_TYPE_UINT32_T:
+    case GCC_JIT_TYPE_INT32_T:
+      size = 32;
+      break;
+    case GCC_JIT_TYPE_UINT64_T:
+    case GCC_JIT_TYPE_INT64_T:
+      size = 64;
+      break;
+    case GCC_JIT_TYPE_UINT128_T:
+    case GCC_JIT_TYPE_INT128_T:
+      size = 128;
+      break;
     case GCC_JIT_TYPE_FLOAT:
       size = FLOAT_TYPE_SIZE;
       break;
@@ -2334,6 +2358,9 @@ recording::memento_of_get_type::get_size ()
     case GCC_JIT_TYPE_LONG_DOUBLE:
       size = LONG_DOUBLE_TYPE_SIZE;
       break;
+    case GCC_JIT_TYPE_SIZE_T:
+      size = MAX_BITS_PER_WORD;
+      break;
     default:
       /* As this function is called by
 	 'gcc_jit_global_set_initializer' and
@@ -2373,6 +2400,16 @@ recording::memento_of_get_type::dereference ()
     case GCC_JIT_TYPE_UNSIGNED_LONG:
     case GCC_JIT_TYPE_LONG_LONG:
     case GCC_JIT_TYPE_UNSIGNED_LONG_LONG:
+    case GCC_JIT_TYPE_UINT8_T:
+    case GCC_JIT_TYPE_UINT16_T:
+    case GCC_JIT_TYPE_UINT32_T:
+    case GCC_JIT_TYPE_UINT64_T:
+    case GCC_JIT_TYPE_UINT128_T:
+    case GCC_JIT_TYPE_INT8_T:
+    case GCC_JIT_TYPE_INT16_T:
+    case GCC_JIT_TYPE_INT32_T:
+    case GCC_JIT_TYPE_INT64_T:
+    case GCC_JIT_TYPE_INT128_T:
     case GCC_JIT_TYPE_FLOAT:
     case GCC_JIT_TYPE_DOUBLE:
     case GCC_JIT_TYPE_LONG_DOUBLE:
@@ -2425,6 +2462,16 @@ recording::memento_of_get_type::is_int () const
     case GCC_JIT_TYPE_UNSIGNED_LONG:
     case GCC_JIT_TYPE_LONG_LONG:
     case GCC_JIT_TYPE_UNSIGNED_LONG_LONG:
+    case GCC_JIT_TYPE_UINT8_T:
+    case GCC_JIT_TYPE_UINT16_T:
+    case GCC_JIT_TYPE_UINT32_T:
+    case GCC_JIT_TYPE_UINT64_T:
+    case GCC_JIT_TYPE_UINT128_T:
+    case GCC_JIT_TYPE_INT8_T:
+    case GCC_JIT_TYPE_INT16_T:
+    case GCC_JIT_TYPE_INT32_T:
+    case GCC_JIT_TYPE_INT64_T:
+    case GCC_JIT_TYPE_INT128_T:
       return true;
 
     case GCC_JIT_TYPE_FLOAT:
@@ -2448,6 +2495,60 @@ recording::memento_of_get_type::is_int () const
     }
 }
 
+/* Implementation of pure virtual hook recording::type::is_signed for
+   recording::memento_of_get_type.  */
+
+bool
+recording::memento_of_get_type::is_signed () const
+{
+  switch (m_kind)
+    {
+    default: gcc_unreachable ();
+
+    case GCC_JIT_TYPE_SIGNED_CHAR:
+    case GCC_JIT_TYPE_CHAR:
+    case GCC_JIT_TYPE_SHORT:
+    case GCC_JIT_TYPE_INT:
+    case GCC_JIT_TYPE_LONG:
+    case GCC_JIT_TYPE_LONG_LONG:
+    case GCC_JIT_TYPE_INT8_T:
+    case GCC_JIT_TYPE_INT16_T:
+    case GCC_JIT_TYPE_INT32_T:
+    case GCC_JIT_TYPE_INT64_T:
+    case GCC_JIT_TYPE_INT128_T:
+      return true;
+
+    case GCC_JIT_TYPE_VOID:
+    case GCC_JIT_TYPE_VOID_PTR:
+    case GCC_JIT_TYPE_BOOL:
+    case GCC_JIT_TYPE_UNSIGNED_CHAR:
+    case GCC_JIT_TYPE_UNSIGNED_SHORT:
+    case GCC_JIT_TYPE_UNSIGNED_INT:
+    case GCC_JIT_TYPE_UNSIGNED_LONG:
+    case GCC_JIT_TYPE_UNSIGNED_LONG_LONG:
+    case GCC_JIT_TYPE_UINT8_T:
+    case GCC_JIT_TYPE_UINT16_T:
+    case GCC_JIT_TYPE_UINT32_T:
+    case GCC_JIT_TYPE_UINT64_T:
+    case GCC_JIT_TYPE_UINT128_T:
+
+    case GCC_JIT_TYPE_FLOAT:
+    case GCC_JIT_TYPE_DOUBLE:
+    case GCC_JIT_TYPE_LONG_DOUBLE:
+
+    case GCC_JIT_TYPE_CONST_CHAR_PTR:
+
+    case GCC_JIT_TYPE_SIZE_T:
+
+    case GCC_JIT_TYPE_FILE_PTR:
+
+    case GCC_JIT_TYPE_COMPLEX_FLOAT:
+    case GCC_JIT_TYPE_COMPLEX_DOUBLE:
+    case GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE:
+      return false;
+    }
+}
+
 /* Implementation of pure virtual hook recording::type::is_float for
    recording::memento_of_get_type.  */
 
@@ -2478,6 +2579,16 @@ recording::memento_of_get_type::is_float () const
     case GCC_JIT_TYPE_UNSIGNED_LONG:
     case GCC_JIT_TYPE_LONG_LONG:
     case GCC_JIT_TYPE_UNSIGNED_LONG_LONG:
+    case GCC_JIT_TYPE_UINT8_T:
+    case GCC_JIT_TYPE_UINT16_T:
+    case GCC_JIT_TYPE_UINT32_T:
+    case GCC_JIT_TYPE_UINT64_T:
+    case GCC_JIT_TYPE_UINT128_T:
+    case GCC_JIT_TYPE_INT8_T:
+    case GCC_JIT_TYPE_INT16_T:
+    case GCC_JIT_TYPE_INT32_T:
+    case GCC_JIT_TYPE_INT64_T:
+    case GCC_JIT_TYPE_INT128_T:
       return false;
 
     case GCC_JIT_TYPE_FLOAT:
@@ -2531,6 +2642,16 @@ recording::memento_of_get_type::is_bool () const
     case GCC_JIT_TYPE_UNSIGNED_LONG:
     case GCC_JIT_TYPE_LONG_LONG:
     case GCC_JIT_TYPE_UNSIGNED_LONG_LONG:
+    case GCC_JIT_TYPE_UINT8_T:
+    case GCC_JIT_TYPE_UINT16_T:
+    case GCC_JIT_TYPE_UINT32_T:
+    case GCC_JIT_TYPE_UINT64_T:
+    case GCC_JIT_TYPE_UINT128_T:
+    case GCC_JIT_TYPE_INT8_T:
+    case GCC_JIT_TYPE_INT16_T:
+    case GCC_JIT_TYPE_INT32_T:
+    case GCC_JIT_TYPE_INT64_T:
+    case GCC_JIT_TYPE_INT128_T:
       return false;
 
     case GCC_JIT_TYPE_FLOAT:
@@ -2601,7 +2722,18 @@ static const char * const get_type_strings[] = {
 
   "complex float", /* GCC_JIT_TYPE_COMPLEX_FLOAT */
   "complex double", /* GCC_JIT_TYPE_COMPLEX_DOUBLE */
-  "complex long double"  /* GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE */
+  "complex long double",  /* GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE */
+
+  "__uint8_t",    /* GCC_JIT_TYPE_UINT8_T */
+  "__uint16_t",   /* GCC_JIT_TYPE_UINT16_T */
+  "__uint32_t",   /* GCC_JIT_TYPE_UINT32_T */
+  "__uint64_t",   /* GCC_JIT_TYPE_UINT64_T */
+  "__uint128_t",  /* GCC_JIT_TYPE_UINT128_T */
+  "__int8_t",     /* GCC_JIT_TYPE_INT8_T */
+  "__int16_t",    /* GCC_JIT_TYPE_INT16_T */
+  "__int32_t",    /* GCC_JIT_TYPE_INT32_T */
+  "__int64_t",    /* GCC_JIT_TYPE_INT64_T */
+  "__int128_t",   /* GCC_JIT_TYPE_INT128_T */
 
 };
 
@@ -2637,7 +2769,17 @@ static const char * const get_type_enum_strings[] = {
   "GCC_JIT_TYPE_FILE_PTR",
   "GCC_JIT_TYPE_COMPLEX_FLOAT",
   "GCC_JIT_TYPE_COMPLEX_DOUBLE",
-  "GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE"
+  "GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE",
+  "GCC_JIT_TYPE_UINT8_T",
+  "GCC_JIT_TYPE_UINT16_T",
+  "GCC_JIT_TYPE_UINT32_T",
+  "GCC_JIT_TYPE_UINT64_T",
+  "GCC_JIT_TYPE_UINT128_T",
+  "GCC_JIT_TYPE_INT8_T",
+  "GCC_JIT_TYPE_INT16_T",
+  "GCC_JIT_TYPE_INT32_T",
+  "GCC_JIT_TYPE_INT64_T",
+  "GCC_JIT_TYPE_INT128_T",
 };
 
 void
diff --git a/gcc/jit/jit-recording.h b/gcc/jit/jit-recording.h
index 846d65cb202..1804aaa6664 100644
--- a/gcc/jit/jit-recording.h
+++ b/gcc/jit/jit-recording.h
@@ -564,6 +564,7 @@ public:
   virtual bool is_void () const { return false; }
   virtual vector_type *is_vector () { return NULL; }
   virtual bool has_known_size () const { return true; }
+  virtual bool is_signed () const = 0;
 
   bool is_numeric () const
   {
@@ -604,12 +605,19 @@ public:
   bool accepts_writes_from (type *rtype) FINAL OVERRIDE
   {
     if (m_kind == GCC_JIT_TYPE_VOID_PTR)
+    {
       if (rtype->is_pointer ())
 	{
 	  /* LHS (this) is type (void *), and the RHS is a pointer:
 	     accept it:  */
 	  return true;
 	}
+    }
+    else if (is_int () && rtype->is_int () && get_size () == rtype->get_size () && is_signed () == rtype->is_signed ())
+    {
+      /* LHS (this) is an integer of the same size and sign as rtype.  */
+      return true;
+    }
 
     return type::accepts_writes_from (rtype);
   }
@@ -620,6 +628,7 @@ public:
   type *is_pointer () FINAL OVERRIDE { return dereference (); }
   type *is_array () FINAL OVERRIDE { return NULL; }
   bool is_void () const FINAL OVERRIDE { return m_kind == GCC_JIT_TYPE_VOID; }
+  bool is_signed () const FINAL OVERRIDE;
 
 public:
   void replay_into (replayer *r) FINAL OVERRIDE;
@@ -653,6 +662,7 @@ 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; }
+  bool is_signed () const FINAL OVERRIDE { return false; }
 
 private:
   string * make_debug_string () FINAL OVERRIDE;
@@ -674,12 +684,15 @@ public:
 
   type *dereference () FINAL OVERRIDE { return m_other_type->dereference (); }
 
+  size_t get_size () FINAL OVERRIDE { return m_other_type->get_size (); };
+
   bool is_int () const FINAL OVERRIDE { return m_other_type->is_int (); }
   bool is_float () const FINAL OVERRIDE { return m_other_type->is_float (); }
   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 (); }
+  bool is_signed () const FINAL OVERRIDE { return m_other_type->is_signed (); }
 
 protected:
   type *m_other_type;
@@ -811,6 +824,7 @@ class array_type : public type
   type *is_pointer () FINAL OVERRIDE { return NULL; }
   type *is_array () FINAL OVERRIDE { return m_element_type; }
   int num_elements () { return m_num_elements; }
+  bool is_signed () const FINAL OVERRIDE { return false; }
 
   void replay_into (replayer *) FINAL OVERRIDE;
 
@@ -844,6 +858,7 @@ public:
   bool is_bool () const FINAL OVERRIDE { return false; }
   type *is_pointer () FINAL OVERRIDE { return NULL; }
   type *is_array () FINAL OVERRIDE { return NULL; }
+  bool is_signed () const FINAL OVERRIDE { return false; }
 
   void replay_into (replayer *) FINAL OVERRIDE;
 
@@ -957,6 +972,7 @@ public:
   bool is_bool () const FINAL OVERRIDE { return false; }
   type *is_pointer () FINAL OVERRIDE { return NULL; }
   type *is_array () FINAL OVERRIDE { return NULL; }
+  bool is_signed () const FINAL OVERRIDE { return false; }
 
   bool has_known_size () const FINAL OVERRIDE { return m_fields != NULL; }
 
diff --git a/gcc/jit/libgccjit.cc b/gcc/jit/libgccjit.cc
index 4c352e8c93d..f09ba6c3e42 100644
--- a/gcc/jit/libgccjit.cc
+++ b/gcc/jit/libgccjit.cc
@@ -345,10 +345,12 @@ jit_error (gcc::jit::recording::context *ctxt,
    gcc::jit::recording::type::accepts_writes_from virtual function on
    LTYPE.  */
 
-static bool
-compatible_types (gcc::jit::recording::type *ltype,
-		  gcc::jit::recording::type *rtype)
+int
+gcc_jit_compatible_types (gcc_jit_type *ltype,
+			  gcc_jit_type *rtype)
 {
+  RETURN_VAL_IF_FAIL (ltype, 0, NULL, NULL, "NULL ltype");
+  RETURN_VAL_IF_FAIL (rtype, 0, NULL, NULL, "NULL rtype");
   return ltype->accepts_writes_from (rtype);
 }
 
@@ -456,7 +458,7 @@ gcc_jit_context_get_type (gcc_jit_context *ctxt,
   JIT_LOG_FUNC (ctxt->get_logger ());
   RETURN_NULL_IF_FAIL_PRINTF1 (
     (type >= GCC_JIT_TYPE_VOID
-     && type <= GCC_JIT_TYPE_FILE_PTR),
+     && type < NUM_GCC_JIT_TYPES),
     ctxt, NULL,
     "unrecognized value for enum gcc_jit_types: %i", type);
 
@@ -523,6 +525,20 @@ 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::get_size method, in
+   jit-recording.cc.  */
+
+ssize_t
+gcc_jit_type_get_size (gcc_jit_type *type)
+{
+  RETURN_VAL_IF_FAIL (type, -1, NULL, NULL, "NULL type");
+  RETURN_VAL_IF_FAIL (type->is_int (), -1, NULL, NULL, "only getting the size of an int type is supported for now");
+  return type->get_size ();
+}
+
 /* Public entrypoint.  See description in libgccjit.h.
 
    After error-checking, the real work is done by the
@@ -2119,7 +2135,7 @@ gcc_jit_context_new_binary_op (gcc_jit_context *ctxt,
   RETURN_NULL_IF_FAIL (a, ctxt, loc, "NULL a");
   RETURN_NULL_IF_FAIL (b, ctxt, loc, "NULL b");
   RETURN_NULL_IF_FAIL_PRINTF4 (
-    a->get_type ()->unqualified () == b->get_type ()->unqualified (),
+    gcc_jit_compatible_types ((gcc_jit_type*)a->get_type ()->unqualified (), (gcc_jit_type*)b->get_type ()->unqualified ()),
     ctxt, loc,
     "mismatching types for binary op:"
     " a: %s (type: %s) b: %s (type: %s)",
@@ -2228,8 +2244,8 @@ gcc_jit_context_new_call (gcc_jit_context *ctxt,
 	param->get_type ()->get_debug_string ());
 
       RETURN_NULL_IF_FAIL_PRINTF6 (
-	compatible_types (param->get_type (),
-			  arg->get_type ()),
+	gcc_jit_compatible_types ((gcc_jit_type*) param->get_type (),
+			  (gcc_jit_type*) arg->get_type ()),
 	ctxt, loc,
 	"mismatching types for argument %d of function \"%s\":"
 	" assignment to param %s (type: %s) from %s (type: %s)",
@@ -2317,8 +2333,8 @@ gcc_jit_context_new_call_through_ptr (gcc_jit_context *ctxt,
 	param_type->get_debug_string ());
 
       RETURN_NULL_IF_FAIL_PRINTF6 (
-	compatible_types (param_type,
-			  arg->get_type ()),
+	gcc_jit_compatible_types ((gcc_jit_type*) param_type,
+			  (gcc_jit_type*) arg->get_type ()),
 	ctxt, loc,
 	"mismatching types for argument %d of fn_ptr: %s:"
 	" assignment to param %d (type: %s) from %s (type: %s)",
@@ -2729,8 +2745,8 @@ gcc_jit_block_add_assignment (gcc_jit_block *block,
   RETURN_IF_FAIL (lvalue, ctxt, loc, "NULL lvalue");
   RETURN_IF_FAIL (rvalue, ctxt, loc, "NULL rvalue");
   RETURN_IF_FAIL_PRINTF4 (
-    compatible_types (lvalue->get_type (),
-		      rvalue->get_type ()),
+    gcc_jit_compatible_types ((gcc_jit_type*) lvalue->get_type (),
+		      (gcc_jit_type*) rvalue->get_type ()),
     ctxt, loc,
     "mismatching types:"
     " assignment to %s (type: %s) from %s (type: %s)",
@@ -2775,8 +2791,8 @@ gcc_jit_block_add_assignment_op (gcc_jit_block *block,
     op);
   RETURN_IF_FAIL (rvalue, ctxt, loc, "NULL rvalue");
   RETURN_IF_FAIL_PRINTF4 (
-    compatible_types (lvalue->get_type (),
-		      rvalue->get_type ()),
+    gcc_jit_compatible_types ((gcc_jit_type*) lvalue->get_type (),
+		      (gcc_jit_type*) rvalue->get_type ()),
     ctxt, loc,
     "mismatching types:"
     " assignment to %s (type: %s) involving %s (type: %s)",
@@ -2932,9 +2948,9 @@ gcc_jit_block_end_with_return (gcc_jit_block *block,
   gcc::jit::recording::function *func = block->get_function ();
   RETURN_IF_FAIL (rvalue, ctxt, loc, "NULL rvalue");
   RETURN_IF_FAIL_PRINTF4 (
-    compatible_types (
-      func->get_return_type (),
-      rvalue->get_type ()),
+    gcc_jit_compatible_types (
+      (gcc_jit_type*) func->get_return_type (),
+      (gcc_jit_type*) rvalue->get_type ()),
     ctxt, loc,
     "mismatching types:"
     " return of %s (type: %s) in function %s (return type: %s)",
@@ -3932,8 +3948,8 @@ gcc_jit_context_new_rvalue_from_vector (gcc_jit_context *ctxt,
       RETURN_NULL_IF_FAIL_PRINTF1 (
 	elements[i], ctxt, loc, "NULL elements[%zi]", i);
       RETURN_NULL_IF_FAIL_PRINTF4 (
-	compatible_types (element_type,
-			  elements[i]->get_type ()),
+	gcc_jit_compatible_types ((gcc_jit_type*) element_type,
+			  (gcc_jit_type*) elements[i]->get_type ()),
 	ctxt, loc,
 	"mismatching type for element[%zi] (expected type: %s): %s (type: %s)",
 	i,
diff --git a/gcc/jit/libgccjit.h b/gcc/jit/libgccjit.h
index 2a5ffacb1fe..1d9da354f31 100644
--- a/gcc/jit/libgccjit.h
+++ b/gcc/jit/libgccjit.h
@@ -574,8 +574,19 @@ enum gcc_jit_types
   /* Complex numbers.  */
   GCC_JIT_TYPE_COMPLEX_FLOAT,
   GCC_JIT_TYPE_COMPLEX_DOUBLE,
-  GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE
-
+  GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE,
+
+  /* Sized integer types.  */
+  GCC_JIT_TYPE_UINT8_T,
+  GCC_JIT_TYPE_UINT16_T,
+  GCC_JIT_TYPE_UINT32_T,
+  GCC_JIT_TYPE_UINT64_T,
+  GCC_JIT_TYPE_UINT128_T,
+  GCC_JIT_TYPE_INT8_T,
+  GCC_JIT_TYPE_INT16_T,
+  GCC_JIT_TYPE_INT32_T,
+  GCC_JIT_TYPE_INT64_T,
+  GCC_JIT_TYPE_INT128_T
 };
 
 extern gcc_jit_type *
@@ -601,6 +612,23 @@ gcc_jit_type_get_const (gcc_jit_type *type);
 extern gcc_jit_type *
 gcc_jit_type_get_volatile (gcc_jit_type *type);
 
+#define LIBGCCJIT_HAVE_SIZED_INTEGERS
+
+/* Given types LTYPE and RTYPE, return non-zero if they are compatible.
+   This API entrypoint was added in LIBGCCJIT_ABI_20; you can test for its
+   presence using
+     #ifdef LIBGCCJIT_HAVE_SIZED_INTEGERS  */
+extern int
+gcc_jit_compatible_types (gcc_jit_type *ltype,
+			  gcc_jit_type *rtype);
+
+/* Given type "T", get its size.
+   This API entrypoint was added in LIBGCCJIT_ABI_20; you can test for its
+   presence using
+     #ifdef LIBGCCJIT_HAVE_SIZED_INTEGERS  */
+extern ssize_t
+gcc_jit_type_get_size (gcc_jit_type *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,
diff --git a/gcc/jit/libgccjit.map b/gcc/jit/libgccjit.map
index f373fd39ac7..1c002786e84 100644
--- a/gcc/jit/libgccjit.map
+++ b/gcc/jit/libgccjit.map
@@ -243,3 +243,9 @@ LIBGCCJIT_ABI_19 {
     gcc_jit_context_new_union_constructor;
     gcc_jit_global_set_initializer_rvalue;
 } LIBGCCJIT_ABI_18;
+
+LIBGCCJIT_ABI_20 {
+  global:
+    gcc_jit_compatible_types;
+    gcc_jit_type_get_size;
+} LIBGCCJIT_ABI_19;
diff --git a/gcc/testsuite/jit.dg/test-types.c b/gcc/testsuite/jit.dg/test-types.c
index 8debcd7eb82..6836597d14e 100644
--- a/gcc/testsuite/jit.dg/test-types.c
+++ b/gcc/testsuite/jit.dg/test-types.c
@@ -1,3 +1,4 @@
+#include <stdint.h>
 #include <stdlib.h>
 #include <stdio.h>
 #include <stddef.h>
@@ -29,6 +30,21 @@ struct zoo
   long long m_long_long;
   unsigned long long m_unsigned_long_long;
 
+  uint8_t m_u8;
+  uint16_t m_u16;
+  uint32_t m_u32;
+  uint64_t m_u64;
+
+  int8_t m_i8;
+  int16_t m_i16;
+  int32_t m_i32;
+  int64_t m_i64;
+
+#ifdef __SIZEOF_INT128__
+  __uint128_t m_u128;
+  __int128_t m_i128;
+#endif
+
   int m_sized_int_type;
 
   float m_float;
@@ -101,6 +117,31 @@ create_code (gcc_jit_context *ctxt, void *user_data)
   gcc_jit_field *field_m_unsigned_long_long =
     CREATE_FIELD (GCC_JIT_TYPE_UNSIGNED_LONG_LONG, "m_unsigned_long_long");
 
+  gcc_jit_field *field_m_u8 =
+    CREATE_FIELD (GCC_JIT_TYPE_UINT8_T, "m_u8");
+  gcc_jit_field *field_m_u16 =
+    CREATE_FIELD (GCC_JIT_TYPE_UINT16_T, "m_u16");
+  gcc_jit_field *field_m_u32 =
+    CREATE_FIELD (GCC_JIT_TYPE_UINT32_T, "m_u32");
+  gcc_jit_field *field_m_u64 =
+    CREATE_FIELD (GCC_JIT_TYPE_UINT64_T, "m_u64");
+
+  gcc_jit_field *field_m_i8 =
+    CREATE_FIELD (GCC_JIT_TYPE_INT8_T, "m_i8");
+  gcc_jit_field *field_m_i16 =
+    CREATE_FIELD (GCC_JIT_TYPE_INT16_T, "m_i16");
+  gcc_jit_field *field_m_i32 =
+    CREATE_FIELD (GCC_JIT_TYPE_INT32_T, "m_i32");
+  gcc_jit_field *field_m_i64 =
+    CREATE_FIELD (GCC_JIT_TYPE_INT64_T, "m_i64");
+
+#ifdef __SIZEOF_INT128__
+  gcc_jit_field *field_m_u128 =
+    CREATE_FIELD (GCC_JIT_TYPE_UINT128_T, "m_u128");
+  gcc_jit_field *field_m_i128 =
+    CREATE_FIELD (GCC_JIT_TYPE_INT128_T, "m_i128");
+#endif
+
   /* Signed int type with sizeof (int): */
   gcc_jit_type *sized_int_type =
     gcc_jit_context_get_int_type (ctxt, sizeof (int), 1);
@@ -147,6 +188,21 @@ create_code (gcc_jit_context *ctxt, void *user_data)
     field_m_long_long,
     field_m_unsigned_long_long,
 
+    field_m_u8,
+    field_m_u16,
+    field_m_u32,
+    field_m_u64,
+
+    field_m_i8,
+    field_m_i16,
+    field_m_i32,
+    field_m_i64,
+
+#ifdef __SIZEOF_INT128__
+    field_m_u128,
+    field_m_i128,
+#endif
+
     field_m_sized_int_type,
 
     field_m_float,
@@ -266,6 +322,61 @@ create_code (gcc_jit_context *ctxt, void *user_data)
       gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_UNSIGNED_LONG_LONG),
       123456789))
 
+  ASSIGN(field_m_u8,
+    gcc_jit_context_new_rvalue_from_int (
+      ctxt,
+      gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_UINT8_T),
+      123))
+  ASSIGN(field_m_u16,
+    gcc_jit_context_new_rvalue_from_int (
+      ctxt,
+      gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_UINT16_T),
+      12345))
+  ASSIGN(field_m_u32,
+    gcc_jit_context_new_rvalue_from_int (
+      ctxt,
+      gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_UINT32_T),
+      123456789))
+  ASSIGN(field_m_u64,
+    gcc_jit_context_new_rvalue_from_int (
+      ctxt,
+      gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_UINT64_T),
+      123456789))
+
+  ASSIGN(field_m_i8,
+    gcc_jit_context_new_rvalue_from_int (
+      ctxt,
+      gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_INT8_T),
+      -1))
+  ASSIGN(field_m_i16,
+    gcc_jit_context_new_rvalue_from_int (
+      ctxt,
+      gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_INT16_T),
+      -2))
+  ASSIGN(field_m_i32,
+    gcc_jit_context_new_rvalue_from_int (
+      ctxt,
+      gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_INT32_T),
+      -3))
+  ASSIGN(field_m_i64,
+    gcc_jit_context_new_rvalue_from_int (
+      ctxt,
+      gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_INT64_T),
+      -4))
+
+#ifdef __SIZEOF_INT128__
+  ASSIGN(field_m_u128,
+    gcc_jit_context_new_rvalue_from_int (
+      ctxt,
+      gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_UINT128_T),
+      123456789))
+  ASSIGN(field_m_i128,
+    gcc_jit_context_new_rvalue_from_int (
+      ctxt,
+      gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_INT128_T),
+      -5))
+#endif
+
   ASSIGN(field_m_sized_int_type,
     gcc_jit_context_new_rvalue_from_int (
       ctxt,
@@ -347,6 +458,21 @@ verify_code (gcc_jit_context *ctxt, gcc_jit_result *result)
   CHECK_VALUE (z.m_long_long, -42);
   CHECK_VALUE (z.m_unsigned_long_long, 123456789);
 
+  CHECK_VALUE (z.m_u8, 123);
+  CHECK_VALUE (z.m_u16, 12345);
+  CHECK_VALUE (z.m_u32, 123456789);
+  CHECK_VALUE (z.m_u64, 123456789);
+
+  CHECK_VALUE (z.m_i8, -1);
+  CHECK_VALUE (z.m_i16, -2);
+  CHECK_VALUE (z.m_i32, -3);
+  CHECK_VALUE (z.m_i64, -4);
+
+#ifdef __SIZEOF_INT128__
+  CHECK_VALUE (z.m_u128, 123456789);
+  CHECK_VALUE (z.m_i128, -5);
+#endif
+
   CHECK_VALUE (z.m_sized_int_type, 500);
 
   CHECK_VALUE (z.m_float, 3.141f);
@@ -358,4 +484,9 @@ verify_code (gcc_jit_context *ctxt, gcc_jit_result *result)
   CHECK_VALUE (z.m_size_t, sizeof (struct zoo));
 
   CHECK_VALUE (z.m_FILE_ptr, stderr);
+
+  if (sizeof(long) == 8)
+    CHECK (gcc_jit_compatible_types (
+      gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_LONG),
+      gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_INT64_T)));
 }
-- 
2.26.2.7.g19db9cfb68.dirty


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

* Re: [PATCH] libgccjit: Add support for sized integer types, including 128-bit integers [PR95325]
  2022-01-21 16:22     ` Antoni Boucher
@ 2022-04-08 20:29       ` Antoni Boucher
  2022-04-12 21:32         ` David Malcolm
  0 siblings, 1 reply; 8+ messages in thread
From: Antoni Boucher @ 2022-04-08 20:29 UTC (permalink / raw)
  To: David Malcolm, Jakub Jelinek; +Cc: jit, gcc-patches

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

David, it seems you missed this email that contains the updated patch
and a few questions.

Attaching the patch again.

Thanks for the reviews!

On Fri, 2022-01-21 at 11:22 -0500, Antoni Boucher via Jit wrote:
> David: this is the email I was talking about in my other email.
> Here's the updated patch.
> 
> By the way, I find the usage of NUM_GCC_JIT_TYPES brittle. Would it
> be
> better to switch to a new enum value for that instead?
> 
> See comments below.
> 
> Le jeudi 20 mai 2021 à 15:25 -0400, David Malcolm a écrit :
> > On Tue, 2021-05-18 at 14:53 +0200, Jakub Jelinek via Jit wrote:
> > > On Tue, May 18, 2021 at 08:23:56AM -0400, Antoni Boucher via Gcc-
> > > patches wrote:
> > > > Hello.
> > > > This patch add support for sized integer types.
> > > > Maybe it should check whether the size of a byte for the
> > > > current
> > > > platform is 8 bits and do other checks so that they're only
> > > > available
> > > > when it makes sense.
> > > > What do you think?
> > > 
> > > Not a review, just a comment.  The 128-bit integral types are
> > > available
> > > only on some targets, the test e.g. the C/C++ FE do for those is
> > > targetm.scalar_mode_supported_p (TImode)
> > > and so even libgccjit shouldn't provide those types
> > > unconditionally.
> > > Similarly for the tests (though it could be guarded with e.g
> > > #ifdef __SIZEOF_INT128__
> > > in that case).
> > > Also, while currently all in tree targets have BITS_PER_UNIT 8
> > > and
> > > therefore QImode is 8-bit, HImode 16-bit, SImode 32-bit and
> > > DImode
> > > 64-
> > > bit,
> > > in the past and maybe in he future there can be targets that
> > > could
> > > have
> > > e.g. 16-bit or 32-bit QImode and then there wouldn't be any
> > > uint8_t/int8_t
> > > and int16_t would be intQImode_type_node etc.
> > >   uint16_type_node = make_or_reuse_type (16, 1);
> > >   uint32_type_node = make_or_reuse_type (32, 1);
> > >   uint64_type_node = make_or_reuse_type (64, 1);
> > >   if (targetm.scalar_mode_supported_p (TImode))
> > >     uint128_type_node = make_or_reuse_type (128, 1);
> > > are always with the given precisions, perhaps jit should use
> > > signed_type_for (uint16_type_node) etc.?
> > 
> > I seem to have mislaid Antoni's original email (sorry), so I'll
> > reply
> > to Jakub's.
> > 
> > > 2021-05-18  Antoni Boucher  <bouanto@zoho.com>
> > > 
> > >     gcc/jit/
> > >             PR target/95325
> > >             * jit-playback.c: Add support for the sized integer
> > > types.
> > >             * jit-recording.c: Add support for the sized integer
> > > types.
> > >             * libgccjit.h (GCC_JIT_TYPE_UINT8_T,
> > > GCC_JIT_TYPE_UINT16_T,
> > >             GCC_JIT_TYPE_UINT32_T, GCC_JIT_TYPE_UINT64_T,
> > >             GCC_JIT_TYPE_UINT128_T, GCC_JIT_TYPE_INT8_T,
> > > GCC_JIT_TYPE_INT16_T,
> > >             GCC_JIT_TYPE_INT32_T, GCC_JIT_TYPE_INT64_T,
> > > GCC_JIT_TYPE_INT128_T):
> > >             New enum variants for gcc_jit_types.
> > >     gcc/testsuite/
> > >             PR target/95325
> > >             * jit.dg/test-types.c: Add tests for sized integer
> > > types.
> > 
> > First a high-level question, why not use (or extend)
> > gcc_jit_context_get_int_type instead?
> 
> If I remember correctly, I believe I had some issues with this
> function, like having it return sometimes long long, and other times
> long for the same size. Maybe that was an issue with a global
> variable
> not cleaned up.
> 
> > 
> > Do we really need to extend enum gcc_jit_types?  Is this a quality-
> > of-
> > life thing for users of the library?
> > 
> > That said, recording::context::get_int_type is currently a bit of a
> > hack, and maybe could probably be improved by using the new enum
> > values
> > the patch adds.
> > 
> > IIRC, libgccjit.c does type-checking by comparing recording::type
> > pointer values; does this patch gives us multiple equivalent types
> > that
> > ought to compare as equal?
> > 
> > If a user gets a type via GCC_JIT_TYPE_INT and gets "another" type
> > via
> > GCC_JIT_TYPE_INT32_T and they happen to be the same on the current
> > target, should libgccjit complain if you use "int" when you meant
> > "int32_t", or accept it?
> 
> I updated the function compatible_types to make them compare as
> equal.
> I believe that it's not used everywhere though, so a cast will be
> necessary in some cases.
> 
> > 
> > Various comments inline below...
> > 
> > > diff --git a/gcc/jit/jit-playback.c b/gcc/jit/jit-playback.c
> > > index c6136301243..40630aa1ab8 100644
> > > --- a/gcc/jit/jit-playback.c
> > > +++ b/gcc/jit/jit-playback.c
> > > @@ -193,6 +193,27 @@ get_tree_node_for_type (enum gcc_jit_types
> > > type_)
> > >      case GCC_JIT_TYPE_UNSIGNED_INT:
> > >        return unsigned_type_node;
> > >  
> > > +    case GCC_JIT_TYPE_UINT8_T:
> > > +      return unsigned_intQI_type_node;
> > > +    case GCC_JIT_TYPE_UINT16_T:
> > > +      return uint16_type_node;
> > > +    case GCC_JIT_TYPE_UINT32_T:
> > > +      return uint32_type_node;
> > > +    case GCC_JIT_TYPE_UINT64_T:
> > > +      return uint64_type_node;
> > > +    case GCC_JIT_TYPE_UINT128_T:
> > > +      return uint128_type_node;
> > > +    case GCC_JIT_TYPE_INT8_T:
> > > +      return intQI_type_node;
> > > +    case GCC_JIT_TYPE_INT16_T:
> > > +      return intHI_type_node;
> > > +    case GCC_JIT_TYPE_INT32_T:
> > > +      return intSI_type_node;
> > > +    case GCC_JIT_TYPE_INT64_T:
> > > +      return intDI_type_node;
> > > +    case GCC_JIT_TYPE_INT128_T:
> > > +      return intTI_type_node;
> > > +
> > 
> > Jakub has already commented that 128 bit types might not be
> > available.
> > 
> > Ideally we'd report that they're not available as soon as the user
> > tries to use them, in gcc_jit_context_get_type, but unfortunately
> > it
> > looks like the test requires us to use
> > targetm.scalar_mode_supported_p,
> > and that requires us to hold the jit mutex and thus be at playback
> > time.
> > 
> > So I think get_tree_node_for_type should take a context, and add an
> > error on the context if there's a failure, returning NULL. 
> > playback::context::get_type is the only caller currently and has
> > handling for an unrecognized value, so I think that logic needs to
> > be
> > moved to get_tree_node_for_type so that the user can distinguish
> > between unrecognized types versus types that are unsupported on
> > this
> > target.
> > 
> > 
> > > diff --git a/gcc/jit/jit-recording.c b/gcc/jit/jit-recording.c
> > > index 117ff70114c..b67ae8bfb78 100644
> > > --- a/gcc/jit/jit-recording.c
> > > +++ b/gcc/jit/jit-recording.c
> > > @@ -2247,6 +2247,18 @@ recording::memento_of_get_type::get_size
> > > ()
> > >      case GCC_JIT_TYPE_UNSIGNED_LONG_LONG:
> > >        size = LONG_LONG_TYPE_SIZE;
> > >        break;
> > > +    case GCC_JIT_TYPE_UINT8_T:
> > > +    case GCC_JIT_TYPE_UINT16_T:
> > > +    case GCC_JIT_TYPE_UINT32_T:
> > > +    case GCC_JIT_TYPE_UINT64_T:
> > > +    case GCC_JIT_TYPE_UINT128_T:
> > > +    case GCC_JIT_TYPE_INT8_T:
> > > +    case GCC_JIT_TYPE_INT16_T:
> > > +    case GCC_JIT_TYPE_INT32_T:
> > > +    case GCC_JIT_TYPE_INT64_T:
> > > +    case GCC_JIT_TYPE_INT128_T:
> > > +      size = 128;
> > > +      break;
> > 
> > This gives 128 bits as the size for all of these types, which seems
> > wrong.
> > 
> > >      case GCC_JIT_TYPE_FLOAT:
> > >        size = FLOAT_TYPE_SIZE;
> > >        break;
> > >      case GCC_JIT_TYPE_FLOAT:
> > 
> > > diff --git a/gcc/jit/libgccjit.h b/gcc/jit/libgccjit.h
> > > index 5c722c2c57f..5d88033a2ab 100644
> > > --- a/gcc/jit/libgccjit.h
> > > +++ b/gcc/jit/libgccjit.h
> > > @@ -548,6 +548,17 @@ enum gcc_jit_types
> > >    GCC_JIT_TYPE_LONG_LONG, /* signed */
> > >    GCC_JIT_TYPE_UNSIGNED_LONG_LONG,
> > >  
> > > +  GCC_JIT_TYPE_UINT8_T,
> > > +  GCC_JIT_TYPE_UINT16_T,
> > > +  GCC_JIT_TYPE_UINT32_T,
> > > +  GCC_JIT_TYPE_UINT64_T,
> > > +  GCC_JIT_TYPE_UINT128_T,
> > > +  GCC_JIT_TYPE_INT8_T,
> > > +  GCC_JIT_TYPE_INT16_T,
> > > +  GCC_JIT_TYPE_INT32_T,
> > > +  GCC_JIT_TYPE_INT64_T,
> > > +  GCC_JIT_TYPE_INT128_T,
> > > +
> > >    /* Floating-point types  */
> > >  
> > >    GCC_JIT_TYPE_FLOAT,
> > 
> > The patch adds the new enum values between existing values of enum
> > gcc_jit_types, effectively changing the ABI, since e.g. the
> > numerical
> > value of GCC_JIT_TYPE_FLOAT changes with this, and there's no way
> > of
> > telling which enum values a binary linked against libgccjit.so is
> > going
> > to supply when it calls into libgccjit.
> > 
> > If we're going to extend the enum, the new values need to be added
> > to
> > the end, extending the ABI rather than changing it.
> 
> Fixed.
> 
> > 
> > I don't think the patch provides a way to detect that the client
> > code
> > is using the new ABI and thus mark it in the metadata.  I'm not
> > sure
> > how to do that.
> 
> Now this patch adds new functions. Does that solve this issue?
> 
> > 
> > > diff --git a/gcc/testsuite/jit.dg/test-types.c
> > > b/gcc/testsuite/jit.dg/test-types.c
> > > index 8debcd7eb82..9c66284f193 100644
> > > --- a/gcc/testsuite/jit.dg/test-types.c
> > > +++ b/gcc/testsuite/jit.dg/test-types.c
> > 
> > [...snip...]
> > 
> > The tests seem reasonable, but as noted by Jakub the 128-bit
> > support
> > needs to be conditionalized.
> > 
> > Hope this is constructive
> > Dave
> > 
> 


[-- Attachment #2: 0001-libgccjit-Add-support-for-sized-integer-types-includ.patch --]
[-- Type: text/x-patch, Size: 31099 bytes --]

From db8836d1e16e432b6f40a26549648f6477d491bc Mon Sep 17 00:00:00 2001
From: Antoni Boucher <bouanto@zoho.com>
Date: Mon, 10 May 2021 19:43:02 -0400
Subject: [PATCH] libgccjit: Add support for sized integer types, including
 128-bit integers [PR95325]

2022-01-19  Antoni Boucher  <bouanto@zoho.com>

gcc/jit/
	PR target/95325
	* docs/topics/compatibility.rst (LIBGCCJIT_ABI_20): New ABI tag.
	* docs/topics/types.rst: Add documentation for the new types
	GCC_JIT_TYPE_UINT8_T, GCC_JIT_TYPE_UINT16_T,
	GCC_JIT_TYPE_UINT32_T, GCC_JIT_TYPE_UINT64_T,
	GCC_JIT_TYPE_UINT128_T, GCC_JIT_TYPE_INT8_T, GCC_JIT_TYPE_INT16_T,
	GCC_JIT_TYPE_INT32_T, GCC_JIT_TYPE_INT64_T, GCC_JIT_TYPE_INT128_T and
	new functions (gcc_jit_compatible_types, gcc_jit_type_get_size).
	* jit-builtins.cc: Add support for BT_UINT128.
	* jit-common.h: Update the value of NUM_GCC_JIT_TYPES.
	* jit-playback.cc: Add support for the sized integer types.
	* jit-recording.cc: Add support for the sized integer types.
	* jit-recording.h: Add support for comparing integer types
	and new function (is_signed).
	* libgccjit.cc: Rename compatible_types to
	gcc_jit_compatible_types and new function (gcc_jit_type_get_size).
	* libgccjit.h: New enum variants for gcc_jit_types
	(GCC_JIT_TYPE_UINT8_T, GCC_JIT_TYPE_UINT16_T,
	GCC_JIT_TYPE_UINT32_T, GCC_JIT_TYPE_UINT64_T,
	GCC_JIT_TYPE_UINT128_T, GCC_JIT_TYPE_INT8_T,
	GCC_JIT_TYPE_INT16_T, GCC_JIT_TYPE_INT32_T,
	GCC_JIT_TYPE_INT64_T, GCC_JIT_TYPE_INT128_T) and new functions
	(gcc_jit_compatible_types, gcc_jit_type_get_size).
	libgccjit.map (LIBGCCJIT_ABI_20): New ABI tag.

gcc/testsuite/
	PR target/95325
	* jit.dg/test-types.c: Add tests for sized integer types.
---
 gcc/jit/docs/topics/compatibility.rst |  20 ++++
 gcc/jit/docs/topics/types.rst         |  41 ++++++++
 gcc/jit/jit-builtins.cc               |   1 +
 gcc/jit/jit-common.h                  |   2 +-
 gcc/jit/jit-playback.cc               |  37 ++++++-
 gcc/jit/jit-recording.cc              | 146 +++++++++++++++++++++++++-
 gcc/jit/jit-recording.h               |  16 +++
 gcc/jit/libgccjit.cc                  |  52 +++++----
 gcc/jit/libgccjit.h                   |  32 +++++-
 gcc/jit/libgccjit.map                 |   6 ++
 gcc/testsuite/jit.dg/test-types.c     | 131 +++++++++++++++++++++++
 11 files changed, 457 insertions(+), 27 deletions(-)

diff --git a/gcc/jit/docs/topics/compatibility.rst b/gcc/jit/docs/topics/compatibility.rst
index 16cebe31a10..73a17664698 100644
--- a/gcc/jit/docs/topics/compatibility.rst
+++ b/gcc/jit/docs/topics/compatibility.rst
@@ -302,3 +302,23 @@ thread-local storage model of a variable:
 section of a variable:
 
   * :func:`gcc_jit_lvalue_set_link_section`
+
+.. _LIBGCCJIT_ABI_20:
+
+``LIBGCCJIT_ABI_20``
+-----------------------
+``LIBGCCJIT_ABI_20`` covers the addition of sized integer types, including
+128-bit integers and helper functions for types:
+
+  * :func:`gcc_jit_compatible_types`
+  * :func:`gcc_jit_type_get_size`
+  * :c:macro:`GCC_JIT_TYPE_UINT8_T`
+  * :c:macro:`GCC_JIT_TYPE_UINT16_T`
+  * :c:macro:`GCC_JIT_TYPE_UINT32_T`
+  * :c:macro:`GCC_JIT_TYPE_UINT64_T`
+  * :c:macro:`GCC_JIT_TYPE_UINT128_T`
+  * :c:macro:`GCC_JIT_TYPE_INT8_T`
+  * :c:macro:`GCC_JIT_TYPE_INT16_T`
+  * :c:macro:`GCC_JIT_TYPE_INT32_T`
+  * :c:macro:`GCC_JIT_TYPE_INT64_T`
+  * :c:macro:`GCC_JIT_TYPE_INT128_T`
diff --git a/gcc/jit/docs/topics/types.rst b/gcc/jit/docs/topics/types.rst
index 9779ad26b6f..ededf49e149 100644
--- a/gcc/jit/docs/topics/types.rst
+++ b/gcc/jit/docs/topics/types.rst
@@ -76,6 +76,16 @@ Standard types
    :c:data:`GCC_JIT_TYPE_UNSIGNED_LONG`        C's ``unsigned long``
    :c:data:`GCC_JIT_TYPE_LONG_LONG`            C99's ``long long`` (signed)
    :c:data:`GCC_JIT_TYPE_UNSIGNED_LONG_LONG`   C99's ``unsigned long long``
+   :c:data:`GCC_JIT_TYPE_UINT8_T`              C99's ``uint8_t``
+   :c:data:`GCC_JIT_TYPE_UINT16_T`             C99's ``uint16_t``
+   :c:data:`GCC_JIT_TYPE_UINT32_T`             C99's ``uint32_t``
+   :c:data:`GCC_JIT_TYPE_UINT64_T`             C99's ``uint64_t``
+   :c:data:`GCC_JIT_TYPE_UINT128_T`            C99's ``__uint128_t``
+   :c:data:`GCC_JIT_TYPE_INT8_T`               C99's ``int8_t``
+   :c:data:`GCC_JIT_TYPE_INT16_T`              C99's ``int16_t``
+   :c:data:`GCC_JIT_TYPE_INT32_T`              C99's ``int32_t``
+   :c:data:`GCC_JIT_TYPE_INT64_T`              C99's ``int64_t``
+   :c:data:`GCC_JIT_TYPE_INT128_T`             C99's ``__int128_t``
    :c:data:`GCC_JIT_TYPE_FLOAT`
    :c:data:`GCC_JIT_TYPE_DOUBLE`
    :c:data:`GCC_JIT_TYPE_LONG_DOUBLE`
@@ -467,3 +477,34 @@ Reflection API
       #ifdef LIBGCCJIT_HAVE_REFLECTION
 
    .. type:: gcc_jit_case
+
+.. function::  int\
+               gcc_jit_compatible_types (gcc_jit_type *ltype,
+                                         gcc_jit_type *rtype)
+
+     Return non-zero if the two types are compatible. For instance,
+     if :c:data:`GCC_JIT_TYPE_UINT64_T` and :c:data:`GCC_JIT_TYPE_UNSIGNED_LONG`
+     are the same size on the target, this will return non-zero.
+     The parameters ``ltype`` and ``rtype`` must be non-NULL.
+     Return 0 on errors.
+
+   This entrypoint was added in :ref:`LIBGCCJIT_ABI_20`; you can test for
+   its presence using
+
+   .. code-block:: c
+
+      #ifdef LIBGCCJIT_HAVE_SIZED_INTEGERS
+
+.. function::  ssize_t\
+               gcc_jit_type_get_size (gcc_jit_type *type)
+
+     Return the size of a type, in bytes. It only works on integer types for now.
+     The parameter ``type`` must be non-NULL.
+     Return -1 on errors.
+
+   This entrypoint was added in :ref:`LIBGCCJIT_ABI_20`; you can test for
+   its presence using
+
+   .. code-block:: c
+
+      #ifdef LIBGCCJIT_HAVE_SIZED_INTEGERS
diff --git a/gcc/jit/jit-builtins.cc b/gcc/jit/jit-builtins.cc
index 71c38eb0948..b949b734332 100644
--- a/gcc/jit/jit-builtins.cc
+++ b/gcc/jit/jit-builtins.cc
@@ -483,6 +483,7 @@ builtins_manager::make_primitive_type (enum jit_builtin_type type_id)
     case BT_UINT16: return m_ctxt->get_int_type (2, false);
     case BT_UINT32: return m_ctxt->get_int_type (4, false);
     case BT_UINT64: return m_ctxt->get_int_type (8, false);
+    case BT_UINT128: return m_ctxt->get_int_type (16, false);
     // case BT_WORD:
     // case BT_UNWINDWORD:
     case BT_FLOAT: return m_ctxt->get_type (GCC_JIT_TYPE_FLOAT);
diff --git a/gcc/jit/jit-common.h b/gcc/jit/jit-common.h
index 1a8cd8bac7b..8c52ddf80e1 100644
--- a/gcc/jit/jit-common.h
+++ b/gcc/jit/jit-common.h
@@ -36,7 +36,7 @@ along with GCC; see the file COPYING3.  If not see
 #endif
 #endif
 
-const int NUM_GCC_JIT_TYPES = GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE + 1;
+const int NUM_GCC_JIT_TYPES = GCC_JIT_TYPE_INT128_T + 1;
 
 /* This comment is included by the docs.
 
diff --git a/gcc/jit/jit-playback.cc b/gcc/jit/jit-playback.cc
index d1835c79863..4683e862611 100644
--- a/gcc/jit/jit-playback.cc
+++ b/gcc/jit/jit-playback.cc
@@ -237,6 +237,36 @@ get_tree_node_for_type (enum gcc_jit_types type_)
     case GCC_JIT_TYPE_UNSIGNED_INT:
       return unsigned_type_node;
 
+    case GCC_JIT_TYPE_UINT8_T:
+      return unsigned_intQI_type_node;
+    case GCC_JIT_TYPE_UINT16_T:
+      return uint16_type_node;
+    case GCC_JIT_TYPE_UINT32_T:
+      return uint32_type_node;
+    case GCC_JIT_TYPE_UINT64_T:
+      return uint64_type_node;
+    case GCC_JIT_TYPE_UINT128_T:
+      if (targetm.scalar_mode_supported_p (TImode))
+        return uint128_type_node;
+
+      add_error (NULL, "gcc_jit_types value unsupported on this target: %i", type_);
+      return NULL;
+
+    case GCC_JIT_TYPE_INT8_T:
+      return intQI_type_node;
+    case GCC_JIT_TYPE_INT16_T:
+      return intHI_type_node;
+    case GCC_JIT_TYPE_INT32_T:
+      return intSI_type_node;
+    case GCC_JIT_TYPE_INT64_T:
+      return intDI_type_node;
+    case GCC_JIT_TYPE_INT128_T:
+      if (targetm.scalar_mode_supported_p (TImode))
+        return intTI_type_node;
+
+      add_error (NULL, "gcc_jit_types value unsupported on this target: %i", type_);
+      return NULL;
+
     case GCC_JIT_TYPE_LONG:
       return long_integer_type_node;
     case GCC_JIT_TYPE_UNSIGNED_LONG:
@@ -268,6 +298,8 @@ get_tree_node_for_type (enum gcc_jit_types type_)
       return complex_long_double_type_node;
     }
 
+  add_error (NULL, "unrecognized (enum gcc_jit_types) value: %i", type_);
+
   return NULL;
 }
 
@@ -280,10 +312,7 @@ get_type (enum gcc_jit_types type_)
 {
   tree type_node = get_tree_node_for_type (type_);
   if (type_node == NULL)
-    {
-      add_error (NULL, "unrecognized (enum gcc_jit_types) value: %i", type_);
-      return NULL;
-    }
+    return NULL;
 
   return new type (type_node);
 }
diff --git a/gcc/jit/jit-recording.cc b/gcc/jit/jit-recording.cc
index 1e3fadfacd7..4ffdad0665f 100644
--- a/gcc/jit/jit-recording.cc
+++ b/gcc/jit/jit-recording.cc
@@ -822,6 +822,10 @@ recording::context::get_int_type (int num_bytes, int is_signed)
     return get_type (is_signed
 		     ? GCC_JIT_TYPE_LONG_LONG
 		     : GCC_JIT_TYPE_UNSIGNED_LONG_LONG);
+  if (num_bits == 128)
+    return get_type (is_signed
+		     ? GCC_JIT_TYPE_INT128_T
+		     : GCC_JIT_TYPE_UINT128_T);
 
   /* Some other size, not corresponding to the C int types.  */
   /* To be written: support arbitrary other sizes, sharing by
@@ -2325,6 +2329,26 @@ recording::memento_of_get_type::get_size ()
     case GCC_JIT_TYPE_UNSIGNED_LONG_LONG:
       size = LONG_LONG_TYPE_SIZE;
       break;
+    case GCC_JIT_TYPE_UINT8_T:
+    case GCC_JIT_TYPE_INT8_T:
+      size = 8;
+      break;
+    case GCC_JIT_TYPE_UINT16_T:
+    case GCC_JIT_TYPE_INT16_T:
+      size = 16;
+      break;
+    case GCC_JIT_TYPE_UINT32_T:
+    case GCC_JIT_TYPE_INT32_T:
+      size = 32;
+      break;
+    case GCC_JIT_TYPE_UINT64_T:
+    case GCC_JIT_TYPE_INT64_T:
+      size = 64;
+      break;
+    case GCC_JIT_TYPE_UINT128_T:
+    case GCC_JIT_TYPE_INT128_T:
+      size = 128;
+      break;
     case GCC_JIT_TYPE_FLOAT:
       size = FLOAT_TYPE_SIZE;
       break;
@@ -2334,6 +2358,9 @@ recording::memento_of_get_type::get_size ()
     case GCC_JIT_TYPE_LONG_DOUBLE:
       size = LONG_DOUBLE_TYPE_SIZE;
       break;
+    case GCC_JIT_TYPE_SIZE_T:
+      size = MAX_BITS_PER_WORD;
+      break;
     default:
       /* As this function is called by
 	 'gcc_jit_global_set_initializer' and
@@ -2373,6 +2400,16 @@ recording::memento_of_get_type::dereference ()
     case GCC_JIT_TYPE_UNSIGNED_LONG:
     case GCC_JIT_TYPE_LONG_LONG:
     case GCC_JIT_TYPE_UNSIGNED_LONG_LONG:
+    case GCC_JIT_TYPE_UINT8_T:
+    case GCC_JIT_TYPE_UINT16_T:
+    case GCC_JIT_TYPE_UINT32_T:
+    case GCC_JIT_TYPE_UINT64_T:
+    case GCC_JIT_TYPE_UINT128_T:
+    case GCC_JIT_TYPE_INT8_T:
+    case GCC_JIT_TYPE_INT16_T:
+    case GCC_JIT_TYPE_INT32_T:
+    case GCC_JIT_TYPE_INT64_T:
+    case GCC_JIT_TYPE_INT128_T:
     case GCC_JIT_TYPE_FLOAT:
     case GCC_JIT_TYPE_DOUBLE:
     case GCC_JIT_TYPE_LONG_DOUBLE:
@@ -2425,6 +2462,16 @@ recording::memento_of_get_type::is_int () const
     case GCC_JIT_TYPE_UNSIGNED_LONG:
     case GCC_JIT_TYPE_LONG_LONG:
     case GCC_JIT_TYPE_UNSIGNED_LONG_LONG:
+    case GCC_JIT_TYPE_UINT8_T:
+    case GCC_JIT_TYPE_UINT16_T:
+    case GCC_JIT_TYPE_UINT32_T:
+    case GCC_JIT_TYPE_UINT64_T:
+    case GCC_JIT_TYPE_UINT128_T:
+    case GCC_JIT_TYPE_INT8_T:
+    case GCC_JIT_TYPE_INT16_T:
+    case GCC_JIT_TYPE_INT32_T:
+    case GCC_JIT_TYPE_INT64_T:
+    case GCC_JIT_TYPE_INT128_T:
       return true;
 
     case GCC_JIT_TYPE_FLOAT:
@@ -2448,6 +2495,60 @@ recording::memento_of_get_type::is_int () const
     }
 }
 
+/* Implementation of pure virtual hook recording::type::is_signed for
+   recording::memento_of_get_type.  */
+
+bool
+recording::memento_of_get_type::is_signed () const
+{
+  switch (m_kind)
+    {
+    default: gcc_unreachable ();
+
+    case GCC_JIT_TYPE_SIGNED_CHAR:
+    case GCC_JIT_TYPE_CHAR:
+    case GCC_JIT_TYPE_SHORT:
+    case GCC_JIT_TYPE_INT:
+    case GCC_JIT_TYPE_LONG:
+    case GCC_JIT_TYPE_LONG_LONG:
+    case GCC_JIT_TYPE_INT8_T:
+    case GCC_JIT_TYPE_INT16_T:
+    case GCC_JIT_TYPE_INT32_T:
+    case GCC_JIT_TYPE_INT64_T:
+    case GCC_JIT_TYPE_INT128_T:
+      return true;
+
+    case GCC_JIT_TYPE_VOID:
+    case GCC_JIT_TYPE_VOID_PTR:
+    case GCC_JIT_TYPE_BOOL:
+    case GCC_JIT_TYPE_UNSIGNED_CHAR:
+    case GCC_JIT_TYPE_UNSIGNED_SHORT:
+    case GCC_JIT_TYPE_UNSIGNED_INT:
+    case GCC_JIT_TYPE_UNSIGNED_LONG:
+    case GCC_JIT_TYPE_UNSIGNED_LONG_LONG:
+    case GCC_JIT_TYPE_UINT8_T:
+    case GCC_JIT_TYPE_UINT16_T:
+    case GCC_JIT_TYPE_UINT32_T:
+    case GCC_JIT_TYPE_UINT64_T:
+    case GCC_JIT_TYPE_UINT128_T:
+
+    case GCC_JIT_TYPE_FLOAT:
+    case GCC_JIT_TYPE_DOUBLE:
+    case GCC_JIT_TYPE_LONG_DOUBLE:
+
+    case GCC_JIT_TYPE_CONST_CHAR_PTR:
+
+    case GCC_JIT_TYPE_SIZE_T:
+
+    case GCC_JIT_TYPE_FILE_PTR:
+
+    case GCC_JIT_TYPE_COMPLEX_FLOAT:
+    case GCC_JIT_TYPE_COMPLEX_DOUBLE:
+    case GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE:
+      return false;
+    }
+}
+
 /* Implementation of pure virtual hook recording::type::is_float for
    recording::memento_of_get_type.  */
 
@@ -2478,6 +2579,16 @@ recording::memento_of_get_type::is_float () const
     case GCC_JIT_TYPE_UNSIGNED_LONG:
     case GCC_JIT_TYPE_LONG_LONG:
     case GCC_JIT_TYPE_UNSIGNED_LONG_LONG:
+    case GCC_JIT_TYPE_UINT8_T:
+    case GCC_JIT_TYPE_UINT16_T:
+    case GCC_JIT_TYPE_UINT32_T:
+    case GCC_JIT_TYPE_UINT64_T:
+    case GCC_JIT_TYPE_UINT128_T:
+    case GCC_JIT_TYPE_INT8_T:
+    case GCC_JIT_TYPE_INT16_T:
+    case GCC_JIT_TYPE_INT32_T:
+    case GCC_JIT_TYPE_INT64_T:
+    case GCC_JIT_TYPE_INT128_T:
       return false;
 
     case GCC_JIT_TYPE_FLOAT:
@@ -2531,6 +2642,16 @@ recording::memento_of_get_type::is_bool () const
     case GCC_JIT_TYPE_UNSIGNED_LONG:
     case GCC_JIT_TYPE_LONG_LONG:
     case GCC_JIT_TYPE_UNSIGNED_LONG_LONG:
+    case GCC_JIT_TYPE_UINT8_T:
+    case GCC_JIT_TYPE_UINT16_T:
+    case GCC_JIT_TYPE_UINT32_T:
+    case GCC_JIT_TYPE_UINT64_T:
+    case GCC_JIT_TYPE_UINT128_T:
+    case GCC_JIT_TYPE_INT8_T:
+    case GCC_JIT_TYPE_INT16_T:
+    case GCC_JIT_TYPE_INT32_T:
+    case GCC_JIT_TYPE_INT64_T:
+    case GCC_JIT_TYPE_INT128_T:
       return false;
 
     case GCC_JIT_TYPE_FLOAT:
@@ -2601,7 +2722,18 @@ static const char * const get_type_strings[] = {
 
   "complex float", /* GCC_JIT_TYPE_COMPLEX_FLOAT */
   "complex double", /* GCC_JIT_TYPE_COMPLEX_DOUBLE */
-  "complex long double"  /* GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE */
+  "complex long double",  /* GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE */
+
+  "__uint8_t",    /* GCC_JIT_TYPE_UINT8_T */
+  "__uint16_t",   /* GCC_JIT_TYPE_UINT16_T */
+  "__uint32_t",   /* GCC_JIT_TYPE_UINT32_T */
+  "__uint64_t",   /* GCC_JIT_TYPE_UINT64_T */
+  "__uint128_t",  /* GCC_JIT_TYPE_UINT128_T */
+  "__int8_t",     /* GCC_JIT_TYPE_INT8_T */
+  "__int16_t",    /* GCC_JIT_TYPE_INT16_T */
+  "__int32_t",    /* GCC_JIT_TYPE_INT32_T */
+  "__int64_t",    /* GCC_JIT_TYPE_INT64_T */
+  "__int128_t",   /* GCC_JIT_TYPE_INT128_T */
 
 };
 
@@ -2637,7 +2769,17 @@ static const char * const get_type_enum_strings[] = {
   "GCC_JIT_TYPE_FILE_PTR",
   "GCC_JIT_TYPE_COMPLEX_FLOAT",
   "GCC_JIT_TYPE_COMPLEX_DOUBLE",
-  "GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE"
+  "GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE",
+  "GCC_JIT_TYPE_UINT8_T",
+  "GCC_JIT_TYPE_UINT16_T",
+  "GCC_JIT_TYPE_UINT32_T",
+  "GCC_JIT_TYPE_UINT64_T",
+  "GCC_JIT_TYPE_UINT128_T",
+  "GCC_JIT_TYPE_INT8_T",
+  "GCC_JIT_TYPE_INT16_T",
+  "GCC_JIT_TYPE_INT32_T",
+  "GCC_JIT_TYPE_INT64_T",
+  "GCC_JIT_TYPE_INT128_T",
 };
 
 void
diff --git a/gcc/jit/jit-recording.h b/gcc/jit/jit-recording.h
index 846d65cb202..1804aaa6664 100644
--- a/gcc/jit/jit-recording.h
+++ b/gcc/jit/jit-recording.h
@@ -564,6 +564,7 @@ public:
   virtual bool is_void () const { return false; }
   virtual vector_type *is_vector () { return NULL; }
   virtual bool has_known_size () const { return true; }
+  virtual bool is_signed () const = 0;
 
   bool is_numeric () const
   {
@@ -604,12 +605,19 @@ public:
   bool accepts_writes_from (type *rtype) FINAL OVERRIDE
   {
     if (m_kind == GCC_JIT_TYPE_VOID_PTR)
+    {
       if (rtype->is_pointer ())
 	{
 	  /* LHS (this) is type (void *), and the RHS is a pointer:
 	     accept it:  */
 	  return true;
 	}
+    }
+    else if (is_int () && rtype->is_int () && get_size () == rtype->get_size () && is_signed () == rtype->is_signed ())
+    {
+      /* LHS (this) is an integer of the same size and sign as rtype.  */
+      return true;
+    }
 
     return type::accepts_writes_from (rtype);
   }
@@ -620,6 +628,7 @@ public:
   type *is_pointer () FINAL OVERRIDE { return dereference (); }
   type *is_array () FINAL OVERRIDE { return NULL; }
   bool is_void () const FINAL OVERRIDE { return m_kind == GCC_JIT_TYPE_VOID; }
+  bool is_signed () const FINAL OVERRIDE;
 
 public:
   void replay_into (replayer *r) FINAL OVERRIDE;
@@ -653,6 +662,7 @@ 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; }
+  bool is_signed () const FINAL OVERRIDE { return false; }
 
 private:
   string * make_debug_string () FINAL OVERRIDE;
@@ -674,12 +684,15 @@ public:
 
   type *dereference () FINAL OVERRIDE { return m_other_type->dereference (); }
 
+  size_t get_size () FINAL OVERRIDE { return m_other_type->get_size (); };
+
   bool is_int () const FINAL OVERRIDE { return m_other_type->is_int (); }
   bool is_float () const FINAL OVERRIDE { return m_other_type->is_float (); }
   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 (); }
+  bool is_signed () const FINAL OVERRIDE { return m_other_type->is_signed (); }
 
 protected:
   type *m_other_type;
@@ -811,6 +824,7 @@ class array_type : public type
   type *is_pointer () FINAL OVERRIDE { return NULL; }
   type *is_array () FINAL OVERRIDE { return m_element_type; }
   int num_elements () { return m_num_elements; }
+  bool is_signed () const FINAL OVERRIDE { return false; }
 
   void replay_into (replayer *) FINAL OVERRIDE;
 
@@ -844,6 +858,7 @@ public:
   bool is_bool () const FINAL OVERRIDE { return false; }
   type *is_pointer () FINAL OVERRIDE { return NULL; }
   type *is_array () FINAL OVERRIDE { return NULL; }
+  bool is_signed () const FINAL OVERRIDE { return false; }
 
   void replay_into (replayer *) FINAL OVERRIDE;
 
@@ -957,6 +972,7 @@ public:
   bool is_bool () const FINAL OVERRIDE { return false; }
   type *is_pointer () FINAL OVERRIDE { return NULL; }
   type *is_array () FINAL OVERRIDE { return NULL; }
+  bool is_signed () const FINAL OVERRIDE { return false; }
 
   bool has_known_size () const FINAL OVERRIDE { return m_fields != NULL; }
 
diff --git a/gcc/jit/libgccjit.cc b/gcc/jit/libgccjit.cc
index 4c352e8c93d..f09ba6c3e42 100644
--- a/gcc/jit/libgccjit.cc
+++ b/gcc/jit/libgccjit.cc
@@ -345,10 +345,12 @@ jit_error (gcc::jit::recording::context *ctxt,
    gcc::jit::recording::type::accepts_writes_from virtual function on
    LTYPE.  */
 
-static bool
-compatible_types (gcc::jit::recording::type *ltype,
-		  gcc::jit::recording::type *rtype)
+int
+gcc_jit_compatible_types (gcc_jit_type *ltype,
+			  gcc_jit_type *rtype)
 {
+  RETURN_VAL_IF_FAIL (ltype, 0, NULL, NULL, "NULL ltype");
+  RETURN_VAL_IF_FAIL (rtype, 0, NULL, NULL, "NULL rtype");
   return ltype->accepts_writes_from (rtype);
 }
 
@@ -456,7 +458,7 @@ gcc_jit_context_get_type (gcc_jit_context *ctxt,
   JIT_LOG_FUNC (ctxt->get_logger ());
   RETURN_NULL_IF_FAIL_PRINTF1 (
     (type >= GCC_JIT_TYPE_VOID
-     && type <= GCC_JIT_TYPE_FILE_PTR),
+     && type < NUM_GCC_JIT_TYPES),
     ctxt, NULL,
     "unrecognized value for enum gcc_jit_types: %i", type);
 
@@ -523,6 +525,20 @@ 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::get_size method, in
+   jit-recording.cc.  */
+
+ssize_t
+gcc_jit_type_get_size (gcc_jit_type *type)
+{
+  RETURN_VAL_IF_FAIL (type, -1, NULL, NULL, "NULL type");
+  RETURN_VAL_IF_FAIL (type->is_int (), -1, NULL, NULL, "only getting the size of an int type is supported for now");
+  return type->get_size ();
+}
+
 /* Public entrypoint.  See description in libgccjit.h.
 
    After error-checking, the real work is done by the
@@ -2119,7 +2135,7 @@ gcc_jit_context_new_binary_op (gcc_jit_context *ctxt,
   RETURN_NULL_IF_FAIL (a, ctxt, loc, "NULL a");
   RETURN_NULL_IF_FAIL (b, ctxt, loc, "NULL b");
   RETURN_NULL_IF_FAIL_PRINTF4 (
-    a->get_type ()->unqualified () == b->get_type ()->unqualified (),
+    gcc_jit_compatible_types ((gcc_jit_type*)a->get_type ()->unqualified (), (gcc_jit_type*)b->get_type ()->unqualified ()),
     ctxt, loc,
     "mismatching types for binary op:"
     " a: %s (type: %s) b: %s (type: %s)",
@@ -2228,8 +2244,8 @@ gcc_jit_context_new_call (gcc_jit_context *ctxt,
 	param->get_type ()->get_debug_string ());
 
       RETURN_NULL_IF_FAIL_PRINTF6 (
-	compatible_types (param->get_type (),
-			  arg->get_type ()),
+	gcc_jit_compatible_types ((gcc_jit_type*) param->get_type (),
+			  (gcc_jit_type*) arg->get_type ()),
 	ctxt, loc,
 	"mismatching types for argument %d of function \"%s\":"
 	" assignment to param %s (type: %s) from %s (type: %s)",
@@ -2317,8 +2333,8 @@ gcc_jit_context_new_call_through_ptr (gcc_jit_context *ctxt,
 	param_type->get_debug_string ());
 
       RETURN_NULL_IF_FAIL_PRINTF6 (
-	compatible_types (param_type,
-			  arg->get_type ()),
+	gcc_jit_compatible_types ((gcc_jit_type*) param_type,
+			  (gcc_jit_type*) arg->get_type ()),
 	ctxt, loc,
 	"mismatching types for argument %d of fn_ptr: %s:"
 	" assignment to param %d (type: %s) from %s (type: %s)",
@@ -2729,8 +2745,8 @@ gcc_jit_block_add_assignment (gcc_jit_block *block,
   RETURN_IF_FAIL (lvalue, ctxt, loc, "NULL lvalue");
   RETURN_IF_FAIL (rvalue, ctxt, loc, "NULL rvalue");
   RETURN_IF_FAIL_PRINTF4 (
-    compatible_types (lvalue->get_type (),
-		      rvalue->get_type ()),
+    gcc_jit_compatible_types ((gcc_jit_type*) lvalue->get_type (),
+		      (gcc_jit_type*) rvalue->get_type ()),
     ctxt, loc,
     "mismatching types:"
     " assignment to %s (type: %s) from %s (type: %s)",
@@ -2775,8 +2791,8 @@ gcc_jit_block_add_assignment_op (gcc_jit_block *block,
     op);
   RETURN_IF_FAIL (rvalue, ctxt, loc, "NULL rvalue");
   RETURN_IF_FAIL_PRINTF4 (
-    compatible_types (lvalue->get_type (),
-		      rvalue->get_type ()),
+    gcc_jit_compatible_types ((gcc_jit_type*) lvalue->get_type (),
+		      (gcc_jit_type*) rvalue->get_type ()),
     ctxt, loc,
     "mismatching types:"
     " assignment to %s (type: %s) involving %s (type: %s)",
@@ -2932,9 +2948,9 @@ gcc_jit_block_end_with_return (gcc_jit_block *block,
   gcc::jit::recording::function *func = block->get_function ();
   RETURN_IF_FAIL (rvalue, ctxt, loc, "NULL rvalue");
   RETURN_IF_FAIL_PRINTF4 (
-    compatible_types (
-      func->get_return_type (),
-      rvalue->get_type ()),
+    gcc_jit_compatible_types (
+      (gcc_jit_type*) func->get_return_type (),
+      (gcc_jit_type*) rvalue->get_type ()),
     ctxt, loc,
     "mismatching types:"
     " return of %s (type: %s) in function %s (return type: %s)",
@@ -3932,8 +3948,8 @@ gcc_jit_context_new_rvalue_from_vector (gcc_jit_context *ctxt,
       RETURN_NULL_IF_FAIL_PRINTF1 (
 	elements[i], ctxt, loc, "NULL elements[%zi]", i);
       RETURN_NULL_IF_FAIL_PRINTF4 (
-	compatible_types (element_type,
-			  elements[i]->get_type ()),
+	gcc_jit_compatible_types ((gcc_jit_type*) element_type,
+			  (gcc_jit_type*) elements[i]->get_type ()),
 	ctxt, loc,
 	"mismatching type for element[%zi] (expected type: %s): %s (type: %s)",
 	i,
diff --git a/gcc/jit/libgccjit.h b/gcc/jit/libgccjit.h
index 2a5ffacb1fe..1d9da354f31 100644
--- a/gcc/jit/libgccjit.h
+++ b/gcc/jit/libgccjit.h
@@ -574,8 +574,19 @@ enum gcc_jit_types
   /* Complex numbers.  */
   GCC_JIT_TYPE_COMPLEX_FLOAT,
   GCC_JIT_TYPE_COMPLEX_DOUBLE,
-  GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE
-
+  GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE,
+
+  /* Sized integer types.  */
+  GCC_JIT_TYPE_UINT8_T,
+  GCC_JIT_TYPE_UINT16_T,
+  GCC_JIT_TYPE_UINT32_T,
+  GCC_JIT_TYPE_UINT64_T,
+  GCC_JIT_TYPE_UINT128_T,
+  GCC_JIT_TYPE_INT8_T,
+  GCC_JIT_TYPE_INT16_T,
+  GCC_JIT_TYPE_INT32_T,
+  GCC_JIT_TYPE_INT64_T,
+  GCC_JIT_TYPE_INT128_T
 };
 
 extern gcc_jit_type *
@@ -601,6 +612,23 @@ gcc_jit_type_get_const (gcc_jit_type *type);
 extern gcc_jit_type *
 gcc_jit_type_get_volatile (gcc_jit_type *type);
 
+#define LIBGCCJIT_HAVE_SIZED_INTEGERS
+
+/* Given types LTYPE and RTYPE, return non-zero if they are compatible.
+   This API entrypoint was added in LIBGCCJIT_ABI_20; you can test for its
+   presence using
+     #ifdef LIBGCCJIT_HAVE_SIZED_INTEGERS  */
+extern int
+gcc_jit_compatible_types (gcc_jit_type *ltype,
+			  gcc_jit_type *rtype);
+
+/* Given type "T", get its size.
+   This API entrypoint was added in LIBGCCJIT_ABI_20; you can test for its
+   presence using
+     #ifdef LIBGCCJIT_HAVE_SIZED_INTEGERS  */
+extern ssize_t
+gcc_jit_type_get_size (gcc_jit_type *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,
diff --git a/gcc/jit/libgccjit.map b/gcc/jit/libgccjit.map
index f373fd39ac7..1c002786e84 100644
--- a/gcc/jit/libgccjit.map
+++ b/gcc/jit/libgccjit.map
@@ -243,3 +243,9 @@ LIBGCCJIT_ABI_19 {
     gcc_jit_context_new_union_constructor;
     gcc_jit_global_set_initializer_rvalue;
 } LIBGCCJIT_ABI_18;
+
+LIBGCCJIT_ABI_20 {
+  global:
+    gcc_jit_compatible_types;
+    gcc_jit_type_get_size;
+} LIBGCCJIT_ABI_19;
diff --git a/gcc/testsuite/jit.dg/test-types.c b/gcc/testsuite/jit.dg/test-types.c
index 8debcd7eb82..6836597d14e 100644
--- a/gcc/testsuite/jit.dg/test-types.c
+++ b/gcc/testsuite/jit.dg/test-types.c
@@ -1,3 +1,4 @@
+#include <stdint.h>
 #include <stdlib.h>
 #include <stdio.h>
 #include <stddef.h>
@@ -29,6 +30,21 @@ struct zoo
   long long m_long_long;
   unsigned long long m_unsigned_long_long;
 
+  uint8_t m_u8;
+  uint16_t m_u16;
+  uint32_t m_u32;
+  uint64_t m_u64;
+
+  int8_t m_i8;
+  int16_t m_i16;
+  int32_t m_i32;
+  int64_t m_i64;
+
+#ifdef __SIZEOF_INT128__
+  __uint128_t m_u128;
+  __int128_t m_i128;
+#endif
+
   int m_sized_int_type;
 
   float m_float;
@@ -101,6 +117,31 @@ create_code (gcc_jit_context *ctxt, void *user_data)
   gcc_jit_field *field_m_unsigned_long_long =
     CREATE_FIELD (GCC_JIT_TYPE_UNSIGNED_LONG_LONG, "m_unsigned_long_long");
 
+  gcc_jit_field *field_m_u8 =
+    CREATE_FIELD (GCC_JIT_TYPE_UINT8_T, "m_u8");
+  gcc_jit_field *field_m_u16 =
+    CREATE_FIELD (GCC_JIT_TYPE_UINT16_T, "m_u16");
+  gcc_jit_field *field_m_u32 =
+    CREATE_FIELD (GCC_JIT_TYPE_UINT32_T, "m_u32");
+  gcc_jit_field *field_m_u64 =
+    CREATE_FIELD (GCC_JIT_TYPE_UINT64_T, "m_u64");
+
+  gcc_jit_field *field_m_i8 =
+    CREATE_FIELD (GCC_JIT_TYPE_INT8_T, "m_i8");
+  gcc_jit_field *field_m_i16 =
+    CREATE_FIELD (GCC_JIT_TYPE_INT16_T, "m_i16");
+  gcc_jit_field *field_m_i32 =
+    CREATE_FIELD (GCC_JIT_TYPE_INT32_T, "m_i32");
+  gcc_jit_field *field_m_i64 =
+    CREATE_FIELD (GCC_JIT_TYPE_INT64_T, "m_i64");
+
+#ifdef __SIZEOF_INT128__
+  gcc_jit_field *field_m_u128 =
+    CREATE_FIELD (GCC_JIT_TYPE_UINT128_T, "m_u128");
+  gcc_jit_field *field_m_i128 =
+    CREATE_FIELD (GCC_JIT_TYPE_INT128_T, "m_i128");
+#endif
+
   /* Signed int type with sizeof (int): */
   gcc_jit_type *sized_int_type =
     gcc_jit_context_get_int_type (ctxt, sizeof (int), 1);
@@ -147,6 +188,21 @@ create_code (gcc_jit_context *ctxt, void *user_data)
     field_m_long_long,
     field_m_unsigned_long_long,
 
+    field_m_u8,
+    field_m_u16,
+    field_m_u32,
+    field_m_u64,
+
+    field_m_i8,
+    field_m_i16,
+    field_m_i32,
+    field_m_i64,
+
+#ifdef __SIZEOF_INT128__
+    field_m_u128,
+    field_m_i128,
+#endif
+
     field_m_sized_int_type,
 
     field_m_float,
@@ -266,6 +322,61 @@ create_code (gcc_jit_context *ctxt, void *user_data)
       gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_UNSIGNED_LONG_LONG),
       123456789))
 
+  ASSIGN(field_m_u8,
+    gcc_jit_context_new_rvalue_from_int (
+      ctxt,
+      gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_UINT8_T),
+      123))
+  ASSIGN(field_m_u16,
+    gcc_jit_context_new_rvalue_from_int (
+      ctxt,
+      gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_UINT16_T),
+      12345))
+  ASSIGN(field_m_u32,
+    gcc_jit_context_new_rvalue_from_int (
+      ctxt,
+      gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_UINT32_T),
+      123456789))
+  ASSIGN(field_m_u64,
+    gcc_jit_context_new_rvalue_from_int (
+      ctxt,
+      gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_UINT64_T),
+      123456789))
+
+  ASSIGN(field_m_i8,
+    gcc_jit_context_new_rvalue_from_int (
+      ctxt,
+      gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_INT8_T),
+      -1))
+  ASSIGN(field_m_i16,
+    gcc_jit_context_new_rvalue_from_int (
+      ctxt,
+      gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_INT16_T),
+      -2))
+  ASSIGN(field_m_i32,
+    gcc_jit_context_new_rvalue_from_int (
+      ctxt,
+      gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_INT32_T),
+      -3))
+  ASSIGN(field_m_i64,
+    gcc_jit_context_new_rvalue_from_int (
+      ctxt,
+      gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_INT64_T),
+      -4))
+
+#ifdef __SIZEOF_INT128__
+  ASSIGN(field_m_u128,
+    gcc_jit_context_new_rvalue_from_int (
+      ctxt,
+      gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_UINT128_T),
+      123456789))
+  ASSIGN(field_m_i128,
+    gcc_jit_context_new_rvalue_from_int (
+      ctxt,
+      gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_INT128_T),
+      -5))
+#endif
+
   ASSIGN(field_m_sized_int_type,
     gcc_jit_context_new_rvalue_from_int (
       ctxt,
@@ -347,6 +458,21 @@ verify_code (gcc_jit_context *ctxt, gcc_jit_result *result)
   CHECK_VALUE (z.m_long_long, -42);
   CHECK_VALUE (z.m_unsigned_long_long, 123456789);
 
+  CHECK_VALUE (z.m_u8, 123);
+  CHECK_VALUE (z.m_u16, 12345);
+  CHECK_VALUE (z.m_u32, 123456789);
+  CHECK_VALUE (z.m_u64, 123456789);
+
+  CHECK_VALUE (z.m_i8, -1);
+  CHECK_VALUE (z.m_i16, -2);
+  CHECK_VALUE (z.m_i32, -3);
+  CHECK_VALUE (z.m_i64, -4);
+
+#ifdef __SIZEOF_INT128__
+  CHECK_VALUE (z.m_u128, 123456789);
+  CHECK_VALUE (z.m_i128, -5);
+#endif
+
   CHECK_VALUE (z.m_sized_int_type, 500);
 
   CHECK_VALUE (z.m_float, 3.141f);
@@ -358,4 +484,9 @@ verify_code (gcc_jit_context *ctxt, gcc_jit_result *result)
   CHECK_VALUE (z.m_size_t, sizeof (struct zoo));
 
   CHECK_VALUE (z.m_FILE_ptr, stderr);
+
+  if (sizeof(long) == 8)
+    CHECK (gcc_jit_compatible_types (
+      gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_LONG),
+      gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_INT64_T)));
 }
-- 
2.26.2.7.g19db9cfb68.dirty


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

* Re: [PATCH] libgccjit: Add support for sized integer types, including 128-bit integers [PR95325]
  2022-04-08 20:29       ` Antoni Boucher
@ 2022-04-12 21:32         ` David Malcolm
  0 siblings, 0 replies; 8+ messages in thread
From: David Malcolm @ 2022-04-12 21:32 UTC (permalink / raw)
  To: Antoni Boucher, Jakub Jelinek; +Cc: jit, gcc-patches

On Fri, 2022-04-08 at 16:29 -0400, Antoni Boucher wrote:
> David, it seems you missed this email that contains the updated patch
> and a few questions.
> 
> Attaching the patch again.
> 
> Thanks for the reviews!

Thanks for the patch.

I updated the patch to fix some minor nits:
- Some whitespace fixes (tab vs spaces, overlong lines, continuation
lines in .rst ". function::" clause)
- I kept compatible_types, with gcc_jit_compatible_types becoming a
thin wrapper around it.  This avoids a bunch of casts in libgccjit.cc
- Regenerated docs/_build/texinfo/libgccjit.texi

Successfully bootstrapped & regrtested on x86_64-pc-linux-gnu.

I've pushed the patch to trunk for GCC 12 as r12-8116-gaf80ea97b61847:

https://gcc.gnu.org/git/?p=gcc.git;a=commitdiff;h=af80ea97b61847d91da0d303e85faed437059092

Dave


> 
> On Fri, 2022-01-21 at 11:22 -0500, Antoni Boucher via Jit wrote:
> > David: this is the email I was talking about in my other email.
> > Here's the updated patch.
> > 
> > By the way, I find the usage of NUM_GCC_JIT_TYPES brittle. Would it
> > be
> > better to switch to a new enum value for that instead?
> > 
> > See comments below.
> > 
> > Le jeudi 20 mai 2021 à 15:25 -0400, David Malcolm a écrit :
> > > On Tue, 2021-05-18 at 14:53 +0200, Jakub Jelinek via Jit wrote:
> > > > On Tue, May 18, 2021 at 08:23:56AM -0400, Antoni Boucher via Gcc-
> > > > patches wrote:
> > > > > Hello.
> > > > > This patch add support for sized integer types.
> > > > > Maybe it should check whether the size of a byte for the
> > > > > current
> > > > > platform is 8 bits and do other checks so that they're only
> > > > > available
> > > > > when it makes sense.
> > > > > What do you think?
> > > > 
> > > > Not a review, just a comment.  The 128-bit integral types are
> > > > available
> > > > only on some targets, the test e.g. the C/C++ FE do for those is
> > > > targetm.scalar_mode_supported_p (TImode)
> > > > and so even libgccjit shouldn't provide those types
> > > > unconditionally.
> > > > Similarly for the tests (though it could be guarded with e.g
> > > > #ifdef __SIZEOF_INT128__
> > > > in that case).
> > > > Also, while currently all in tree targets have BITS_PER_UNIT 8
> > > > and
> > > > therefore QImode is 8-bit, HImode 16-bit, SImode 32-bit and
> > > > DImode
> > > > 64-
> > > > bit,
> > > > in the past and maybe in he future there can be targets that
> > > > could
> > > > have
> > > > e.g. 16-bit or 32-bit QImode and then there wouldn't be any
> > > > uint8_t/int8_t
> > > > and int16_t would be intQImode_type_node etc.
> > > >   uint16_type_node = make_or_reuse_type (16, 1);
> > > >   uint32_type_node = make_or_reuse_type (32, 1);
> > > >   uint64_type_node = make_or_reuse_type (64, 1);
> > > >   if (targetm.scalar_mode_supported_p (TImode))
> > > >     uint128_type_node = make_or_reuse_type (128, 1);
> > > > are always with the given precisions, perhaps jit should use
> > > > signed_type_for (uint16_type_node) etc.?
> > > 
> > > I seem to have mislaid Antoni's original email (sorry), so I'll
> > > reply
> > > to Jakub's.
> > > 
> > > > 2021-05-18  Antoni Boucher  <bouanto@zoho.com>
> > > > 
> > > >     gcc/jit/
> > > >             PR target/95325
> > > >             * jit-playback.c: Add support for the sized integer
> > > > types.
> > > >             * jit-recording.c: Add support for the sized integer
> > > > types.
> > > >             * libgccjit.h (GCC_JIT_TYPE_UINT8_T,
> > > > GCC_JIT_TYPE_UINT16_T,
> > > >             GCC_JIT_TYPE_UINT32_T, GCC_JIT_TYPE_UINT64_T,
> > > >             GCC_JIT_TYPE_UINT128_T, GCC_JIT_TYPE_INT8_T,
> > > > GCC_JIT_TYPE_INT16_T,
> > > >             GCC_JIT_TYPE_INT32_T, GCC_JIT_TYPE_INT64_T,
> > > > GCC_JIT_TYPE_INT128_T):
> > > >             New enum variants for gcc_jit_types.
> > > >     gcc/testsuite/
> > > >             PR target/95325
> > > >             * jit.dg/test-types.c: Add tests for sized integer
> > > > types.
> > > 
> > > First a high-level question, why not use (or extend)
> > > gcc_jit_context_get_int_type instead?
> > 
> > If I remember correctly, I believe I had some issues with this
> > function, like having it return sometimes long long, and other times
> > long for the same size. Maybe that was an issue with a global
> > variable
> > not cleaned up.
> > 
> > > 
> > > Do we really need to extend enum gcc_jit_types?  Is this a quality-
> > > of-
> > > life thing for users of the library?
> > > 
> > > That said, recording::context::get_int_type is currently a bit of a
> > > hack, and maybe could probably be improved by using the new enum
> > > values
> > > the patch adds.
> > > 
> > > IIRC, libgccjit.c does type-checking by comparing recording::type
> > > pointer values; does this patch gives us multiple equivalent types
> > > that
> > > ought to compare as equal?
> > > 
> > > If a user gets a type via GCC_JIT_TYPE_INT and gets "another" type
> > > via
> > > GCC_JIT_TYPE_INT32_T and they happen to be the same on the current
> > > target, should libgccjit complain if you use "int" when you meant
> > > "int32_t", or accept it?
> > 
> > I updated the function compatible_types to make them compare as
> > equal.
> > I believe that it's not used everywhere though, so a cast will be
> > necessary in some cases.
> > 
> > > 
> > > Various comments inline below...
> > > 
> > > > diff --git a/gcc/jit/jit-playback.c b/gcc/jit/jit-playback.c
> > > > index c6136301243..40630aa1ab8 100644
> > > > --- a/gcc/jit/jit-playback.c
> > > > +++ b/gcc/jit/jit-playback.c
> > > > @@ -193,6 +193,27 @@ get_tree_node_for_type (enum gcc_jit_types
> > > > type_)
> > > >      case GCC_JIT_TYPE_UNSIGNED_INT:
> > > >        return unsigned_type_node;
> > > >  
> > > > +    case GCC_JIT_TYPE_UINT8_T:
> > > > +      return unsigned_intQI_type_node;
> > > > +    case GCC_JIT_TYPE_UINT16_T:
> > > > +      return uint16_type_node;
> > > > +    case GCC_JIT_TYPE_UINT32_T:
> > > > +      return uint32_type_node;
> > > > +    case GCC_JIT_TYPE_UINT64_T:
> > > > +      return uint64_type_node;
> > > > +    case GCC_JIT_TYPE_UINT128_T:
> > > > +      return uint128_type_node;
> > > > +    case GCC_JIT_TYPE_INT8_T:
> > > > +      return intQI_type_node;
> > > > +    case GCC_JIT_TYPE_INT16_T:
> > > > +      return intHI_type_node;
> > > > +    case GCC_JIT_TYPE_INT32_T:
> > > > +      return intSI_type_node;
> > > > +    case GCC_JIT_TYPE_INT64_T:
> > > > +      return intDI_type_node;
> > > > +    case GCC_JIT_TYPE_INT128_T:
> > > > +      return intTI_type_node;
> > > > +
> > > 
> > > Jakub has already commented that 128 bit types might not be
> > > available.
> > > 
> > > Ideally we'd report that they're not available as soon as the user
> > > tries to use them, in gcc_jit_context_get_type, but unfortunately
> > > it
> > > looks like the test requires us to use
> > > targetm.scalar_mode_supported_p,
> > > and that requires us to hold the jit mutex and thus be at playback
> > > time.
> > > 
> > > So I think get_tree_node_for_type should take a context, and add an
> > > error on the context if there's a failure, returning NULL. 
> > > playback::context::get_type is the only caller currently and has
> > > handling for an unrecognized value, so I think that logic needs to
> > > be
> > > moved to get_tree_node_for_type so that the user can distinguish
> > > between unrecognized types versus types that are unsupported on
> > > this
> > > target.
> > > 
> > > 
> > > > diff --git a/gcc/jit/jit-recording.c b/gcc/jit/jit-recording.c
> > > > index 117ff70114c..b67ae8bfb78 100644
> > > > --- a/gcc/jit/jit-recording.c
> > > > +++ b/gcc/jit/jit-recording.c
> > > > @@ -2247,6 +2247,18 @@ recording::memento_of_get_type::get_size
> > > > ()
> > > >      case GCC_JIT_TYPE_UNSIGNED_LONG_LONG:
> > > >        size = LONG_LONG_TYPE_SIZE;
> > > >        break;
> > > > +    case GCC_JIT_TYPE_UINT8_T:
> > > > +    case GCC_JIT_TYPE_UINT16_T:
> > > > +    case GCC_JIT_TYPE_UINT32_T:
> > > > +    case GCC_JIT_TYPE_UINT64_T:
> > > > +    case GCC_JIT_TYPE_UINT128_T:
> > > > +    case GCC_JIT_TYPE_INT8_T:
> > > > +    case GCC_JIT_TYPE_INT16_T:
> > > > +    case GCC_JIT_TYPE_INT32_T:
> > > > +    case GCC_JIT_TYPE_INT64_T:
> > > > +    case GCC_JIT_TYPE_INT128_T:
> > > > +      size = 128;
> > > > +      break;
> > > 
> > > This gives 128 bits as the size for all of these types, which seems
> > > wrong.
> > > 
> > > >      case GCC_JIT_TYPE_FLOAT:
> > > >        size = FLOAT_TYPE_SIZE;
> > > >        break;
> > > >      case GCC_JIT_TYPE_FLOAT:
> > > 
> > > > diff --git a/gcc/jit/libgccjit.h b/gcc/jit/libgccjit.h
> > > > index 5c722c2c57f..5d88033a2ab 100644
> > > > --- a/gcc/jit/libgccjit.h
> > > > +++ b/gcc/jit/libgccjit.h
> > > > @@ -548,6 +548,17 @@ enum gcc_jit_types
> > > >    GCC_JIT_TYPE_LONG_LONG, /* signed */
> > > >    GCC_JIT_TYPE_UNSIGNED_LONG_LONG,
> > > >  
> > > > +  GCC_JIT_TYPE_UINT8_T,
> > > > +  GCC_JIT_TYPE_UINT16_T,
> > > > +  GCC_JIT_TYPE_UINT32_T,
> > > > +  GCC_JIT_TYPE_UINT64_T,
> > > > +  GCC_JIT_TYPE_UINT128_T,
> > > > +  GCC_JIT_TYPE_INT8_T,
> > > > +  GCC_JIT_TYPE_INT16_T,
> > > > +  GCC_JIT_TYPE_INT32_T,
> > > > +  GCC_JIT_TYPE_INT64_T,
> > > > +  GCC_JIT_TYPE_INT128_T,
> > > > +
> > > >    /* Floating-point types  */
> > > >  
> > > >    GCC_JIT_TYPE_FLOAT,
> > > 
> > > The patch adds the new enum values between existing values of enum
> > > gcc_jit_types, effectively changing the ABI, since e.g. the
> > > numerical
> > > value of GCC_JIT_TYPE_FLOAT changes with this, and there's no way
> > > of
> > > telling which enum values a binary linked against libgccjit.so is
> > > going
> > > to supply when it calls into libgccjit.
> > > 
> > > If we're going to extend the enum, the new values need to be added
> > > to
> > > the end, extending the ABI rather than changing it.
> > 
> > Fixed.
> > 
> > > 
> > > I don't think the patch provides a way to detect that the client
> > > code
> > > is using the new ABI and thus mark it in the metadata.  I'm not
> > > sure
> > > how to do that.
> > 
> > Now this patch adds new functions. Does that solve this issue?
> > 
> > > 
> > > > diff --git a/gcc/testsuite/jit.dg/test-types.c
> > > > b/gcc/testsuite/jit.dg/test-types.c
> > > > index 8debcd7eb82..9c66284f193 100644
> > > > --- a/gcc/testsuite/jit.dg/test-types.c
> > > > +++ b/gcc/testsuite/jit.dg/test-types.c
> > > 
> > > [...snip...]
> > > 
> > > The tests seem reasonable, but as noted by Jakub the 128-bit
> > > support
> > > needs to be conditionalized.
> > > 
> > > Hope this is constructive
> > > Dave
> > > 
> > 
> 



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

end of thread, other threads:[~2022-04-12 21:32 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-05-18 12:23 [PATCH] libgccjit: Add support for sized integer types, including 128-bit integers [PR95325] Antoni Boucher
2021-05-18 12:36 ` Antoni Boucher
2021-05-18 12:53 ` Jakub Jelinek
2021-05-20 19:25   ` David Malcolm
2022-01-04  3:13     ` Antoni Boucher
2022-01-21 16:22     ` Antoni Boucher
2022-04-08 20:29       ` Antoni Boucher
2022-04-12 21:32         ` David Malcolm

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).