public inbox for jit@gcc.gnu.org
 help / color / mirror / Atom feed
* [PATCH] libgccjit: Make new_array_type take unsigned long
@ 2023-12-07 22:29 Antoni Boucher
  2023-12-08  1:04 ` David Malcolm
  0 siblings, 1 reply; 4+ messages in thread
From: Antoni Boucher @ 2023-12-07 22:29 UTC (permalink / raw)
  To: jit, gcc-patches; +Cc: David Malcolm

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

Hi.
This patches update gcc_jit_context_new_array_type to take the size as
an unsigned long instead of a int, to allow creating bigger array
types.

I haven't written the ChangeLog yet because I wasn't sure it's allowed
to change the type of a function like that.
If it isn't, what would you suggest?

Thanks.

[-- Attachment #2: 0001-libgccjit-Make-new_array_type-take-unsigned-long.patch --]
[-- Type: text/x-patch, Size: 4630 bytes --]

From 59b7e8af99d5f680e6d622631b1b75609fe1b982 Mon Sep 17 00:00:00 2001
From: Antoni Boucher <bouanto@zoho.com>
Date: Sat, 4 Mar 2023 00:44:49 -0500
Subject: [PATCH] libgccjit: Make new_array_type take unsigned long

---
 gcc/jit/jit-playback.cc  | 2 +-
 gcc/jit/jit-playback.h   | 2 +-
 gcc/jit/jit-recording.cc | 6 +++---
 gcc/jit/jit-recording.h  | 8 ++++----
 gcc/jit/libgccjit.cc     | 2 +-
 gcc/jit/libgccjit.h      | 2 +-
 6 files changed, 11 insertions(+), 11 deletions(-)

diff --git a/gcc/jit/jit-playback.cc b/gcc/jit/jit-playback.cc
index dddd537f3b1..9da05b0b4b1 100644
--- a/gcc/jit/jit-playback.cc
+++ b/gcc/jit/jit-playback.cc
@@ -326,7 +326,7 @@ playback::type *
 playback::context::
 new_array_type (playback::location *loc,
 		playback::type *element_type,
-		int num_elements)
+		unsigned long num_elements)
 {
   gcc_assert (element_type);
 
diff --git a/gcc/jit/jit-playback.h b/gcc/jit/jit-playback.h
index b0166f8f6ce..848cb5f25e8 100644
--- a/gcc/jit/jit-playback.h
+++ b/gcc/jit/jit-playback.h
@@ -69,7 +69,7 @@ public:
   type *
   new_array_type (location *loc,
 		  type *element_type,
-		  int num_elements);
+		  unsigned long num_elements);
 
   field *
   new_field (location *loc,
diff --git a/gcc/jit/jit-recording.cc b/gcc/jit/jit-recording.cc
index 9b5b8005ebe..4ab4f0df25b 100644
--- a/gcc/jit/jit-recording.cc
+++ b/gcc/jit/jit-recording.cc
@@ -840,7 +840,7 @@ recording::context::get_int_type (int num_bytes, int is_signed)
 recording::type *
 recording::context::new_array_type (recording::location *loc,
 				    recording::type *element_type,
-				    int num_elements)
+				    unsigned long num_elements)
 {
   if (struct_ *s = element_type->dyn_cast_struct ())
     if (!s->get_fields ())
@@ -3113,7 +3113,7 @@ recording::string *
 recording::array_type::make_debug_string ()
 {
   return string::from_printf (m_ctxt,
-			      "%s[%d]",
+			      "%s[%ld]",
 			      m_element_type->get_debug_string (),
 			      m_num_elements);
 }
@@ -3129,7 +3129,7 @@ recording::array_type::write_reproducer (reproducer &r)
 	   "    gcc_jit_context_new_array_type (%s,\n"
 	   "                                    %s, /* gcc_jit_location *loc */\n"
 	   "                                    %s, /* gcc_jit_type *element_type */\n"
-	   "                                    %i); /* int num_elements */\n",
+	   "                                    %li); /* int num_elements */\n",
 	   id,
 	   r.get_identifier (get_context ()),
 	   r.get_identifier (m_loc),
diff --git a/gcc/jit/jit-recording.h b/gcc/jit/jit-recording.h
index 4a8082991fb..0bb035a5ae5 100644
--- a/gcc/jit/jit-recording.h
+++ b/gcc/jit/jit-recording.h
@@ -91,7 +91,7 @@ public:
   type *
   new_array_type (location *loc,
 		  type *element_type,
-		  int num_elements);
+		  unsigned long num_elements);
 
   field *
   new_field (location *loc,
@@ -859,7 +859,7 @@ class array_type : public type
   array_type (context *ctxt,
 	      location *loc,
 	      type *element_type,
-	      int num_elements)
+	      unsigned long num_elements)
   : type (ctxt),
     m_loc (loc),
     m_element_type (element_type),
@@ -873,7 +873,7 @@ class array_type : public type
   bool is_bool () const final override { return false; }
   type *is_pointer () final override { return NULL; }
   type *is_array () final override { return m_element_type; }
-  int num_elements () { return m_num_elements; }
+  unsigned long num_elements () { return m_num_elements; }
   bool is_signed () const final override { return false; }
 
   void replay_into (replayer *) final override;
@@ -885,7 +885,7 @@ class array_type : public type
  private:
   location *m_loc;
   type *m_element_type;
-  int m_num_elements;
+  unsigned long m_num_elements;
 };
 
 class function_type : public type
diff --git a/gcc/jit/libgccjit.cc b/gcc/jit/libgccjit.cc
index 0451b4df7f9..1424a5c305f 100644
--- a/gcc/jit/libgccjit.cc
+++ b/gcc/jit/libgccjit.cc
@@ -766,7 +766,7 @@ gcc_jit_type *
 gcc_jit_context_new_array_type (gcc_jit_context *ctxt,
 				gcc_jit_location *loc,
 				gcc_jit_type *element_type,
-				int num_elements)
+				unsigned long num_elements)
 {
   RETURN_NULL_IF_FAIL (ctxt, NULL, loc, "NULL context");
   JIT_LOG_FUNC (ctxt->get_logger ());
diff --git a/gcc/jit/libgccjit.h b/gcc/jit/libgccjit.h
index 749f6c24177..88399b6124d 100644
--- a/gcc/jit/libgccjit.h
+++ b/gcc/jit/libgccjit.h
@@ -661,7 +661,7 @@ extern gcc_jit_type *
 gcc_jit_context_new_array_type (gcc_jit_context *ctxt,
 				gcc_jit_location *loc,
 				gcc_jit_type *element_type,
-				int num_elements);
+				unsigned long num_elements);
 
 /* Struct-handling.  */
 
-- 
2.43.0


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

* Re: [PATCH] libgccjit: Make new_array_type take unsigned long
  2023-12-07 22:29 [PATCH] libgccjit: Make new_array_type take unsigned long Antoni Boucher
@ 2023-12-08  1:04 ` David Malcolm
  2024-02-22  0:45   ` Antoni Boucher
  0 siblings, 1 reply; 4+ messages in thread
From: David Malcolm @ 2023-12-08  1:04 UTC (permalink / raw)
  To: Antoni Boucher, jit, gcc-patches

On Thu, 2023-12-07 at 17:29 -0500, Antoni Boucher wrote:
> Hi.
> This patches update gcc_jit_context_new_array_type to take the size
> as
> an unsigned long instead of a int, to allow creating bigger array
> types.
> 
> I haven't written the ChangeLog yet because I wasn't sure it's
> allowed
> to change the type of a function like that.
> If it isn't, what would you suggest?

We've kept ABI compatibility all the way back to the version in GCC 5,
so it seems a shame to break ABI.

How about a new API entrypoint:
  gcc_jit_context_new_array_type_unsigned_long
whilst keeping the old one.

Then everything internally can use "unsigned long"; we just keep the
old entrypoint accepting int (which internally promotes the arg to
unsigned long, if positive, sharing all the implementation).

Alternatively, I think there may be a way to do this with symbol
versioning:
  https://gcc.gnu.org/wiki/SymbolVersioning
see e.g. Section 3.7 of Ulrich Drepper's "How To Write Shared
Libraries", but I'm a bit wary of cross-platform compatibility with
that.

Dave



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

* Re: [PATCH] libgccjit: Make new_array_type take unsigned long
  2023-12-08  1:04 ` David Malcolm
@ 2024-02-22  0:45   ` Antoni Boucher
  2024-02-23 14:55     ` Antoni Boucher
  0 siblings, 1 reply; 4+ messages in thread
From: Antoni Boucher @ 2024-02-22  0:45 UTC (permalink / raw)
  To: David Malcolm, jit, gcc-patches

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

Thanks for the review.

Here's the updated patch.

On Thu, 2023-12-07 at 20:04 -0500, David Malcolm wrote:
> On Thu, 2023-12-07 at 17:29 -0500, Antoni Boucher wrote:
> > Hi.
> > This patches update gcc_jit_context_new_array_type to take the size
> > as
> > an unsigned long instead of a int, to allow creating bigger array
> > types.
> > 
> > I haven't written the ChangeLog yet because I wasn't sure it's
> > allowed
> > to change the type of a function like that.
> > If it isn't, what would you suggest?
> 
> We've kept ABI compatibility all the way back to the version in GCC
> 5,
> so it seems a shame to break ABI.
> 
> How about a new API entrypoint:
>   gcc_jit_context_new_array_type_unsigned_long
> whilst keeping the old one.
> 
> Then everything internally can use "unsigned long"; we just keep the
> old entrypoint accepting int (which internally promotes the arg to
> unsigned long, if positive, sharing all the implementation).
> 
> Alternatively, I think there may be a way to do this with symbol
> versioning:
>   https://gcc.gnu.org/wiki/SymbolVersioning
> see e.g. Section 3.7 of Ulrich Drepper's "How To Write Shared
> Libraries", but I'm a bit wary of cross-platform compatibility with
> that.
> 
> Dave
> 
> 


[-- Attachment #2: 0001-libgccjit-Make-new_array_type-take-unsigned-long.patch --]
[-- Type: text/x-patch, Size: 13638 bytes --]

From 4886f05909b0770a673f220a8957d0104d5014d3 Mon Sep 17 00:00:00 2001
From: Antoni Boucher <bouanto@zoho.com>
Date: Sat, 4 Mar 2023 00:44:49 -0500
Subject: [PATCH] libgccjit: Make new_array_type take unsigned long

gcc/jit/ChangeLog:

	* jit-playback.cc (new_array_type): Change num_elements type to
	unsigned long.
	* jit-playback.h (new_array_type): Change num_elements type to
	unsigned long.
	* jit-recording.cc (recording::context::new_array_type): Change
	num_elements type to unsigned long.
	(recording::array_type::make_debug_string): Use unsigned long
	format.
	(recording::array_type::write_reproducer): Switch to
	gcc_jit_context_new_array_type_unsigned_long.
	* jit-recording.h (class array_type): Change num_elements type
	to unsigned long.
	(new_array_type): Change num_elements type to unsigned long.
	(num_elements): Change return type to unsigned long.
	* libgccjit.cc (gcc_jit_context_new_array_type_unsigned_long):
	New function.
	* libgccjit.h (gcc_jit_context_new_array_type_unsigned_long):
	New function.
	* libgccjit.map: New function.

gcc/testsuite/ChangeLog:

	* jit.dg/all-non-failing-tests.h: Add test-arrays-unsigned-long.c.
	* jit.dg/test-arrays-unsigned-long.c: New test.
---
 gcc/jit/jit-playback.cc                       |   2 +-
 gcc/jit/jit-playback.h                        |   2 +-
 gcc/jit/jit-recording.cc                      |  12 +-
 gcc/jit/jit-recording.h                       |   8 +-
 gcc/jit/libgccjit.cc                          |  12 +-
 gcc/jit/libgccjit.h                           |   7 +
 gcc/jit/libgccjit.map                         |   5 +
 gcc/testsuite/jit.dg/all-non-failing-tests.h  |  10 ++
 .../jit.dg/test-arrays-unsigned-long.c        | 165 ++++++++++++++++++
 9 files changed, 210 insertions(+), 13 deletions(-)
 create mode 100644 gcc/testsuite/jit.dg/test-arrays-unsigned-long.c

diff --git a/gcc/jit/jit-playback.cc b/gcc/jit/jit-playback.cc
index 6baa838af10..b3775a18a83 100644
--- a/gcc/jit/jit-playback.cc
+++ b/gcc/jit/jit-playback.cc
@@ -327,7 +327,7 @@ playback::type *
 playback::context::
 new_array_type (playback::location *loc,
 		playback::type *element_type,
-		int num_elements)
+		unsigned long num_elements)
 {
   gcc_assert (element_type);
 
diff --git a/gcc/jit/jit-playback.h b/gcc/jit/jit-playback.h
index aa6a086613c..7cbb2d1f8d8 100644
--- a/gcc/jit/jit-playback.h
+++ b/gcc/jit/jit-playback.h
@@ -80,7 +80,7 @@ public:
   type *
   new_array_type (location *loc,
 		  type *element_type,
-		  int num_elements);
+		  unsigned long num_elements);
 
   field *
   new_field (location *loc,
diff --git a/gcc/jit/jit-recording.cc b/gcc/jit/jit-recording.cc
index 68a2e860c1f..3a05e91c140 100644
--- a/gcc/jit/jit-recording.cc
+++ b/gcc/jit/jit-recording.cc
@@ -841,7 +841,7 @@ recording::context::get_int_type (int num_bytes, int is_signed)
 recording::type *
 recording::context::new_array_type (recording::location *loc,
 				    recording::type *element_type,
-				    int num_elements)
+				    unsigned long num_elements)
 {
   if (struct_ *s = element_type->dyn_cast_struct ())
     if (!s->get_fields ())
@@ -3129,7 +3129,7 @@ recording::string *
 recording::array_type::make_debug_string ()
 {
   return string::from_printf (m_ctxt,
-			      "%s[%d]",
+			      "%s[%ld]",
 			      m_element_type->get_debug_string (),
 			      m_num_elements);
 }
@@ -3142,10 +3142,10 @@ recording::array_type::write_reproducer (reproducer &r)
 {
   const char *id = r.make_identifier (this, "array_type");
   r.write ("  gcc_jit_type *%s =\n"
-	   "    gcc_jit_context_new_array_type (%s,\n"
-	   "                                    %s, /* gcc_jit_location *loc */\n"
-	   "                                    %s, /* gcc_jit_type *element_type */\n"
-	   "                                    %i); /* int num_elements */\n",
+	   "    gcc_jit_context_new_array_type_unsigned_long (%s,\n"
+	   "                                                  %s, /* gcc_jit_location *loc */\n"
+	   "                                                  %s, /* gcc_jit_type *element_type */\n"
+	   "                                                  %li); /* int num_elements */\n",
 	   id,
 	   r.get_identifier (get_context ()),
 	   r.get_identifier (m_loc),
diff --git a/gcc/jit/jit-recording.h b/gcc/jit/jit-recording.h
index d8d16f4fe29..c359c2526cc 100644
--- a/gcc/jit/jit-recording.h
+++ b/gcc/jit/jit-recording.h
@@ -95,7 +95,7 @@ public:
   type *
   new_array_type (location *loc,
 		  type *element_type,
-		  int num_elements);
+		  unsigned long num_elements);
 
   field *
   new_field (location *loc,
@@ -878,7 +878,7 @@ class array_type : public type
   array_type (context *ctxt,
 	      location *loc,
 	      type *element_type,
-	      int num_elements)
+	      unsigned long num_elements)
   : type (ctxt),
     m_loc (loc),
     m_element_type (element_type),
@@ -892,7 +892,7 @@ class array_type : public type
   bool is_bool () const final override { return false; }
   type *is_pointer () final override { return NULL; }
   type *is_array () final override { return m_element_type; }
-  int num_elements () { return m_num_elements; }
+  unsigned long num_elements () { return m_num_elements; }
   bool is_signed () const final override { return false; }
 
   void replay_into (replayer *) final override;
@@ -904,7 +904,7 @@ class array_type : public type
  private:
   location *m_loc;
   type *m_element_type;
-  int m_num_elements;
+  unsigned long m_num_elements;
 };
 
 class function_type : public type
diff --git a/gcc/jit/libgccjit.cc b/gcc/jit/libgccjit.cc
index f40a9781405..32b6df6d80f 100644
--- a/gcc/jit/libgccjit.cc
+++ b/gcc/jit/libgccjit.cc
@@ -767,12 +767,22 @@ gcc_jit_context_new_array_type (gcc_jit_context *ctxt,
 				gcc_jit_location *loc,
 				gcc_jit_type *element_type,
 				int num_elements)
+{
+  RETURN_NULL_IF_FAIL (num_elements >= 0, ctxt, NULL, "negative size");
+  return gcc_jit_context_new_array_type_unsigned_long (ctxt, loc, element_type,
+    (unsigned long) num_elements);
+}
+
+gcc_jit_type *
+gcc_jit_context_new_array_type_unsigned_long (gcc_jit_context *ctxt,
+					      gcc_jit_location *loc,
+					      gcc_jit_type *element_type,
+					      unsigned long num_elements)
 {
   RETURN_NULL_IF_FAIL (ctxt, NULL, loc, "NULL context");
   JIT_LOG_FUNC (ctxt->get_logger ());
   /* LOC can be NULL.  */
   RETURN_NULL_IF_FAIL (element_type, ctxt, loc, "NULL type");
-  RETURN_NULL_IF_FAIL (num_elements >= 0, ctxt, NULL, "negative size");
   RETURN_NULL_IF_FAIL (!element_type->is_void (), ctxt, loc,
 		       "void type for elements");
 
diff --git a/gcc/jit/libgccjit.h b/gcc/jit/libgccjit.h
index 74e847b2dec..f40fb9fc60c 100644
--- a/gcc/jit/libgccjit.h
+++ b/gcc/jit/libgccjit.h
@@ -663,6 +663,13 @@ gcc_jit_context_new_array_type (gcc_jit_context *ctxt,
 				gcc_jit_type *element_type,
 				int num_elements);
 
+/* Given type "T", get type "T[N]" (for a constant N).  */
+extern gcc_jit_type *
+gcc_jit_context_new_array_type_unsigned_long (gcc_jit_context *ctxt,
+					      gcc_jit_location *loc,
+					      gcc_jit_type *element_type,
+					      unsigned long num_elements);
+
 /* Struct-handling.  */
 
 /* Create a field, for use within a struct or union.  */
diff --git a/gcc/jit/libgccjit.map b/gcc/jit/libgccjit.map
index 99aa5970be1..d6efc0ddf56 100644
--- a/gcc/jit/libgccjit.map
+++ b/gcc/jit/libgccjit.map
@@ -289,3 +289,8 @@ LIBGCCJIT_ABI_27 {
   global:
     gcc_jit_context_new_sizeof;
 } LIBGCCJIT_ABI_26;
+
+LIBGCCJIT_ABI_28 {
+  global:
+    gcc_jit_context_new_array_type_unsigned_long;
+} LIBGCCJIT_ABI_27;
diff --git a/gcc/testsuite/jit.dg/all-non-failing-tests.h b/gcc/testsuite/jit.dg/all-non-failing-tests.h
index 14a0a321550..223d98bcbc4 100644
--- a/gcc/testsuite/jit.dg/all-non-failing-tests.h
+++ b/gcc/testsuite/jit.dg/all-non-failing-tests.h
@@ -66,6 +66,13 @@
 #undef create_code
 #undef verify_code
 
+/* test-arrays-unsigned-long.c */
+#define create_code create_code_arrays_unsigned_long
+#define verify_code verify_code_arrays_unsigned_long
+#include "test-arrays-unsigned-long.c"
+#undef create_code
+#undef verify_code
+
 /* test-autovectorize.c */
 #define create_code create_code_autovectorize
 #define verify_code verify_code_autovectorize
@@ -461,6 +468,9 @@ const struct testcase testcases[] = {
   {"arrays",
    create_code_arrays,
    verify_code_arrays},
+  {"arrays-unsigned-long",
+   create_code_arrays_unsigned_long,
+   verify_code_arrays_unsigned_long},
   {"autovectorize",
    create_code_autovectorize,
    verify_code_autovectorize},
diff --git a/gcc/testsuite/jit.dg/test-arrays-unsigned-long.c b/gcc/testsuite/jit.dg/test-arrays-unsigned-long.c
new file mode 100644
index 00000000000..0a82c7046ea
--- /dev/null
+++ b/gcc/testsuite/jit.dg/test-arrays-unsigned-long.c
@@ -0,0 +1,165 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <stddef.h>
+
+#include "libgccjit.h"
+
+#include "harness.h"
+
+#define ARRAY_SIZE (4)
+
+/* Verify that struct layout works properly when adding an array field.  */
+struct array_holder2
+{
+  float m_before;
+  int m_ints[ARRAY_SIZE];
+  float m_after;
+};
+
+void
+create_code (gcc_jit_context *ctxt, void *user_data)
+{
+  /* Let's try to inject the equivalent of:
+
+     void
+     test_array_unsigned_long (struct array_holder2 *ah)
+     {
+	ah->m_before = 4.0f;
+	for i in 0 to (ARRAY_SIZE - 1):
+	  ah->m_ints[i] = (i * i);
+	ah->m_after = 2.0f;
+     }
+  */
+  gcc_jit_type *void_type =
+    gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_VOID);
+  gcc_jit_type *float_type =
+    gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_FLOAT);
+  gcc_jit_type *int_type =
+    gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_INT);
+
+  gcc_jit_field *field_m_before =
+    gcc_jit_context_new_field (ctxt, NULL, float_type, "m_before");
+  gcc_jit_field *field_m_ints =
+    gcc_jit_context_new_field (
+    ctxt, NULL,
+    gcc_jit_context_new_array_type_unsigned_long (ctxt, NULL, int_type, ARRAY_SIZE),
+    "m_ints");
+  gcc_jit_field *field_m_after =
+    gcc_jit_context_new_field (ctxt, NULL, float_type, "m_after");
+
+  gcc_jit_field *fields[] = {
+    field_m_before,
+    field_m_ints,
+    field_m_after,
+  };
+
+  gcc_jit_struct *struct_type =
+    gcc_jit_context_new_struct_type (
+      ctxt,
+      NULL,
+      "array_holder2",
+      3, fields);
+
+  gcc_jit_type *struct_ptr_type =
+    gcc_jit_type_get_pointer (gcc_jit_struct_as_type (struct_type));
+
+  /* Build the test_fn.  */
+  gcc_jit_param *param_ah =
+    gcc_jit_context_new_param (ctxt, NULL, struct_ptr_type, "ah");
+  gcc_jit_function *func =
+    gcc_jit_context_new_function (ctxt, NULL,
+				  GCC_JIT_FUNCTION_EXPORTED,
+				  void_type,
+				  "test_array_unsigned_long",
+				  1, &param_ah,
+				  0);
+
+  gcc_jit_block *initial = gcc_jit_function_new_block (func, "initial");
+  gcc_jit_block *loop_test = gcc_jit_function_new_block (func, "loop_test");
+  gcc_jit_block *loop_body = gcc_jit_function_new_block (func, "loop_body");
+  gcc_jit_block *final = gcc_jit_function_new_block (func, "final");
+
+  /* "ah->m_before = 4.0f;" */
+  gcc_jit_block_add_assignment (
+    initial, NULL,
+    gcc_jit_rvalue_dereference_field (
+      gcc_jit_param_as_rvalue (param_ah), NULL, field_m_before),
+    gcc_jit_context_new_rvalue_from_int (ctxt, float_type, 4));
+
+  gcc_jit_block_add_comment (initial, NULL,
+			     "for i in 0 to (ARRAY_SIZE - 1):");
+  gcc_jit_lvalue *i =
+    gcc_jit_function_new_local (func, NULL, int_type, "i");
+  gcc_jit_block_add_assignment (initial, NULL,
+      i,
+      gcc_jit_context_zero (ctxt, int_type));
+
+  gcc_jit_block_end_with_jump (initial, NULL, loop_test);
+
+  gcc_jit_block_end_with_conditional (loop_test, NULL,
+    gcc_jit_context_new_comparison (
+      ctxt, NULL,
+      GCC_JIT_COMPARISON_LT,
+      gcc_jit_lvalue_as_rvalue (i),
+      gcc_jit_context_new_rvalue_from_int (ctxt, int_type, ARRAY_SIZE)),
+    loop_body,
+    final);
+
+  gcc_jit_block_add_comment (loop_body, NULL, "ah->m_ints[i] = (i * i);");
+  gcc_jit_block_add_assignment (
+    loop_body, NULL,
+    gcc_jit_context_new_array_access (
+      ctxt, NULL,
+      gcc_jit_lvalue_as_rvalue (gcc_jit_rvalue_dereference_field (
+	gcc_jit_param_as_rvalue (param_ah),
+	NULL,
+	field_m_ints)),
+      gcc_jit_lvalue_as_rvalue (i)),
+    gcc_jit_context_new_binary_op (
+      ctxt, NULL,
+      GCC_JIT_BINARY_OP_MULT,
+      int_type,
+      gcc_jit_lvalue_as_rvalue (i),
+      gcc_jit_lvalue_as_rvalue (i)));
+
+  /* "i++" */
+  gcc_jit_block_add_assignment_op (
+    loop_body, NULL,
+    i,
+    GCC_JIT_BINARY_OP_PLUS,
+    gcc_jit_context_one (ctxt, int_type));
+
+  gcc_jit_block_end_with_jump (loop_body, NULL, loop_test);
+
+ /* ah->m_after = 2.0f; */
+  gcc_jit_block_add_assignment (
+    final, NULL,
+    gcc_jit_rvalue_dereference_field (
+      gcc_jit_param_as_rvalue (param_ah), NULL, field_m_after),
+    gcc_jit_context_new_rvalue_from_int (ctxt, float_type, 2));
+  gcc_jit_block_end_with_void_return (final, NULL);
+
+}
+
+void
+verify_code (gcc_jit_context *ctxt, gcc_jit_result *result)
+{
+  typedef void (*fn_type) (struct array_holder2 *ah);
+
+  CHECK_NON_NULL (result);
+  fn_type test_array_unsigned_long =
+    (fn_type)gcc_jit_result_get_code (result, "test_array_unsigned_long");
+  CHECK_NON_NULL (test_array_unsigned_long);
+
+  struct array_holder2 ah;
+  memset (&ah, 0xf0, sizeof (ah));
+
+  test_array_unsigned_long (&ah);
+  CHECK_VALUE (ah.m_before, 4.0f);
+  CHECK_VALUE (ah.m_ints[0], 0);
+  CHECK_VALUE (ah.m_ints[1], 1);
+  CHECK_VALUE (ah.m_ints[2], 4);
+  CHECK_VALUE (ah.m_ints[3], 9);
+  CHECK_VALUE (ah.m_after, 2.0f);
+
+}
-- 
2.43.0


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

* Re: [PATCH] libgccjit: Make new_array_type take unsigned long
  2024-02-22  0:45   ` Antoni Boucher
@ 2024-02-23 14:55     ` Antoni Boucher
  0 siblings, 0 replies; 4+ messages in thread
From: Antoni Boucher @ 2024-02-23 14:55 UTC (permalink / raw)
  To: David Malcolm, jit, gcc-patches

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

I had forgotten to add the doc since there is now a new API.
Here it is.

On Wed, 2024-02-21 at 19:45 -0500, Antoni Boucher wrote:
> Thanks for the review.
> 
> Here's the updated patch.
> 
> On Thu, 2023-12-07 at 20:04 -0500, David Malcolm wrote:
> > On Thu, 2023-12-07 at 17:29 -0500, Antoni Boucher wrote:
> > > Hi.
> > > This patches update gcc_jit_context_new_array_type to take the
> > > size
> > > as
> > > an unsigned long instead of a int, to allow creating bigger array
> > > types.
> > > 
> > > I haven't written the ChangeLog yet because I wasn't sure it's
> > > allowed
> > > to change the type of a function like that.
> > > If it isn't, what would you suggest?
> > 
> > We've kept ABI compatibility all the way back to the version in GCC
> > 5,
> > so it seems a shame to break ABI.
> > 
> > How about a new API entrypoint:
> >   gcc_jit_context_new_array_type_unsigned_long
> > whilst keeping the old one.
> > 
> > Then everything internally can use "unsigned long"; we just keep
> > the
> > old entrypoint accepting int (which internally promotes the arg to
> > unsigned long, if positive, sharing all the implementation).
> > 
> > Alternatively, I think there may be a way to do this with symbol
> > versioning:
> >   https://gcc.gnu.org/wiki/SymbolVersioning
> > see e.g. Section 3.7 of Ulrich Drepper's "How To Write Shared
> > Libraries", but I'm a bit wary of cross-platform compatibility with
> > that.
> > 
> > Dave
> > 
> > 
> 


[-- Attachment #2: 0001-libgccjit-Add-gcc_jit_context_new_array_type_unsigne.patch --]
[-- Type: text/x-patch, Size: 15977 bytes --]

From 00156914f0805788190706935962fe65ab5fd7cb Mon Sep 17 00:00:00 2001
From: Antoni Boucher <bouanto@zoho.com>
Date: Sat, 4 Mar 2023 00:44:49 -0500
Subject: [PATCH] libgccjit: Add gcc_jit_context_new_array_type_unsigned_long

gcc/jit/ChangeLog:

	* docs/topics/compatibility.rst (LIBGCCJIT_ABI_28): New ABI tag.
	* docs/topics/types.rst: Document
	gcc_jit_context_new_array_type_unsigned_long.
	* jit-playback.cc (new_array_type): Change num_elements type to
	unsigned long.
	* jit-playback.h (new_array_type): Change num_elements type to
	unsigned long.
	* jit-recording.cc (recording::context::new_array_type): Change
	num_elements type to unsigned long.
	(recording::array_type::make_debug_string): Use unsigned long
	format.
	(recording::array_type::write_reproducer): Switch to
	gcc_jit_context_new_array_type_unsigned_long.
	* jit-recording.h (class array_type): Change num_elements type
	to unsigned long.
	(new_array_type): Change num_elements type to unsigned long.
	(num_elements): Change return type to unsigned long.
	* libgccjit.cc (gcc_jit_context_new_array_type_unsigned_long):
	New function.
	* libgccjit.h (gcc_jit_context_new_array_type_unsigned_long):
	New function.
	* libgccjit.map: New function.

gcc/testsuite/ChangeLog:

	* jit.dg/all-non-failing-tests.h: Add test-arrays-unsigned-long.c.
	* jit.dg/test-arrays-unsigned-long.c: New test.
---
 gcc/jit/docs/topics/compatibility.rst         |   7 +
 gcc/jit/docs/topics/types.rst                 |  18 ++
 gcc/jit/jit-playback.cc                       |   2 +-
 gcc/jit/jit-playback.h                        |   2 +-
 gcc/jit/jit-recording.cc                      |  12 +-
 gcc/jit/jit-recording.h                       |   8 +-
 gcc/jit/libgccjit.cc                          |  12 +-
 gcc/jit/libgccjit.h                           |  14 ++
 gcc/jit/libgccjit.map                         |   5 +
 gcc/testsuite/jit.dg/all-non-failing-tests.h  |  10 ++
 .../jit.dg/test-arrays-unsigned-long.c        | 165 ++++++++++++++++++
 11 files changed, 242 insertions(+), 13 deletions(-)
 create mode 100644 gcc/testsuite/jit.dg/test-arrays-unsigned-long.c

diff --git a/gcc/jit/docs/topics/compatibility.rst b/gcc/jit/docs/topics/compatibility.rst
index 9cfb054f653..a8c8cf45630 100644
--- a/gcc/jit/docs/topics/compatibility.rst
+++ b/gcc/jit/docs/topics/compatibility.rst
@@ -397,3 +397,10 @@ on functions and variables:
 --------------------
 ``LIBGCCJIT_ABI_27`` covers the addition of
 :func:`gcc_jit_context_new_sizeof`
+
+.. _LIBGCCJIT_ABI_28:
+
+``LIBGCCJIT_ABI_28``
+--------------------
+``LIBGCCJIT_ABI_28`` covers the addition of
+:func:`gcc_jit_context_new_array_type_unsigned_long`
diff --git a/gcc/jit/docs/topics/types.rst b/gcc/jit/docs/topics/types.rst
index bb51f037b7e..d83ecd3cf13 100644
--- a/gcc/jit/docs/topics/types.rst
+++ b/gcc/jit/docs/topics/types.rst
@@ -160,6 +160,24 @@ Pointers, `const`, and `volatile`
 
    Given non-`void` type "T", get type "T[N]" (for a constant N).
 
+.. function::  gcc_jit_type *\
+               gcc_jit_context_new_array_type_unsigned_long (gcc_jit_context *ctxt, \
+                                                             gcc_jit_location *loc, \
+                                                             gcc_jit_type *element_type, \
+                                                             unsigned long num_elements)
+
+   Given non-`void` type "T", get type "T[N]" (for a constant N).
+
+   This is the same as gcc_jit_context_new_array_type, but the type of
+   ``num_elements` different and thus allows creating bigger array types.
+
+   This API entrypoint was added in :ref:`LIBGCCJIT_ABI_28`; you can test
+   for its presence using
+
+   .. code-block:: c
+
+      #ifdef LIBGCCJIT_HAVE_gcc_jit_context_new_array_type_unsigned_long
+
 .. function::  gcc_jit_type *\
                gcc_jit_type_get_aligned (gcc_jit_type *type, \
                                          size_t alignment_in_bytes)
diff --git a/gcc/jit/jit-playback.cc b/gcc/jit/jit-playback.cc
index 6baa838af10..b3775a18a83 100644
--- a/gcc/jit/jit-playback.cc
+++ b/gcc/jit/jit-playback.cc
@@ -327,7 +327,7 @@ playback::type *
 playback::context::
 new_array_type (playback::location *loc,
 		playback::type *element_type,
-		int num_elements)
+		unsigned long num_elements)
 {
   gcc_assert (element_type);
 
diff --git a/gcc/jit/jit-playback.h b/gcc/jit/jit-playback.h
index aa6a086613c..7cbb2d1f8d8 100644
--- a/gcc/jit/jit-playback.h
+++ b/gcc/jit/jit-playback.h
@@ -80,7 +80,7 @@ public:
   type *
   new_array_type (location *loc,
 		  type *element_type,
-		  int num_elements);
+		  unsigned long num_elements);
 
   field *
   new_field (location *loc,
diff --git a/gcc/jit/jit-recording.cc b/gcc/jit/jit-recording.cc
index 68a2e860c1f..3a05e91c140 100644
--- a/gcc/jit/jit-recording.cc
+++ b/gcc/jit/jit-recording.cc
@@ -841,7 +841,7 @@ recording::context::get_int_type (int num_bytes, int is_signed)
 recording::type *
 recording::context::new_array_type (recording::location *loc,
 				    recording::type *element_type,
-				    int num_elements)
+				    unsigned long num_elements)
 {
   if (struct_ *s = element_type->dyn_cast_struct ())
     if (!s->get_fields ())
@@ -3129,7 +3129,7 @@ recording::string *
 recording::array_type::make_debug_string ()
 {
   return string::from_printf (m_ctxt,
-			      "%s[%d]",
+			      "%s[%ld]",
 			      m_element_type->get_debug_string (),
 			      m_num_elements);
 }
@@ -3142,10 +3142,10 @@ recording::array_type::write_reproducer (reproducer &r)
 {
   const char *id = r.make_identifier (this, "array_type");
   r.write ("  gcc_jit_type *%s =\n"
-	   "    gcc_jit_context_new_array_type (%s,\n"
-	   "                                    %s, /* gcc_jit_location *loc */\n"
-	   "                                    %s, /* gcc_jit_type *element_type */\n"
-	   "                                    %i); /* int num_elements */\n",
+	   "    gcc_jit_context_new_array_type_unsigned_long (%s,\n"
+	   "                                                  %s, /* gcc_jit_location *loc */\n"
+	   "                                                  %s, /* gcc_jit_type *element_type */\n"
+	   "                                                  %li); /* int num_elements */\n",
 	   id,
 	   r.get_identifier (get_context ()),
 	   r.get_identifier (m_loc),
diff --git a/gcc/jit/jit-recording.h b/gcc/jit/jit-recording.h
index d8d16f4fe29..c359c2526cc 100644
--- a/gcc/jit/jit-recording.h
+++ b/gcc/jit/jit-recording.h
@@ -95,7 +95,7 @@ public:
   type *
   new_array_type (location *loc,
 		  type *element_type,
-		  int num_elements);
+		  unsigned long num_elements);
 
   field *
   new_field (location *loc,
@@ -878,7 +878,7 @@ class array_type : public type
   array_type (context *ctxt,
 	      location *loc,
 	      type *element_type,
-	      int num_elements)
+	      unsigned long num_elements)
   : type (ctxt),
     m_loc (loc),
     m_element_type (element_type),
@@ -892,7 +892,7 @@ class array_type : public type
   bool is_bool () const final override { return false; }
   type *is_pointer () final override { return NULL; }
   type *is_array () final override { return m_element_type; }
-  int num_elements () { return m_num_elements; }
+  unsigned long num_elements () { return m_num_elements; }
   bool is_signed () const final override { return false; }
 
   void replay_into (replayer *) final override;
@@ -904,7 +904,7 @@ class array_type : public type
  private:
   location *m_loc;
   type *m_element_type;
-  int m_num_elements;
+  unsigned long m_num_elements;
 };
 
 class function_type : public type
diff --git a/gcc/jit/libgccjit.cc b/gcc/jit/libgccjit.cc
index f40a9781405..32b6df6d80f 100644
--- a/gcc/jit/libgccjit.cc
+++ b/gcc/jit/libgccjit.cc
@@ -767,12 +767,22 @@ gcc_jit_context_new_array_type (gcc_jit_context *ctxt,
 				gcc_jit_location *loc,
 				gcc_jit_type *element_type,
 				int num_elements)
+{
+  RETURN_NULL_IF_FAIL (num_elements >= 0, ctxt, NULL, "negative size");
+  return gcc_jit_context_new_array_type_unsigned_long (ctxt, loc, element_type,
+    (unsigned long) num_elements);
+}
+
+gcc_jit_type *
+gcc_jit_context_new_array_type_unsigned_long (gcc_jit_context *ctxt,
+					      gcc_jit_location *loc,
+					      gcc_jit_type *element_type,
+					      unsigned long num_elements)
 {
   RETURN_NULL_IF_FAIL (ctxt, NULL, loc, "NULL context");
   JIT_LOG_FUNC (ctxt->get_logger ());
   /* LOC can be NULL.  */
   RETURN_NULL_IF_FAIL (element_type, ctxt, loc, "NULL type");
-  RETURN_NULL_IF_FAIL (num_elements >= 0, ctxt, NULL, "negative size");
   RETURN_NULL_IF_FAIL (!element_type->is_void (), ctxt, loc,
 		       "void type for elements");
 
diff --git a/gcc/jit/libgccjit.h b/gcc/jit/libgccjit.h
index 74e847b2dec..92663e1ff7b 100644
--- a/gcc/jit/libgccjit.h
+++ b/gcc/jit/libgccjit.h
@@ -663,6 +663,20 @@ gcc_jit_context_new_array_type (gcc_jit_context *ctxt,
 				gcc_jit_type *element_type,
 				int num_elements);
 
+/* Given type "T", get type "T[N]" (for a constant N).
+
+   This API entrypoint was added in LIBGCCJIT_ABI_28; you can test for its
+   presence using
+     #ifdef LIBGCCJIT_HAVE_gcc_jit_context_new_array_type_unsigned_long
+*/
+extern gcc_jit_type *
+gcc_jit_context_new_array_type_unsigned_long (gcc_jit_context *ctxt,
+					      gcc_jit_location *loc,
+					      gcc_jit_type *element_type,
+					      unsigned long num_elements);
+
+#define LIBGCCJIT_HAVE_gcc_jit_context_new_array_type_unsigned_long
+
 /* Struct-handling.  */
 
 /* Create a field, for use within a struct or union.  */
diff --git a/gcc/jit/libgccjit.map b/gcc/jit/libgccjit.map
index 99aa5970be1..d6efc0ddf56 100644
--- a/gcc/jit/libgccjit.map
+++ b/gcc/jit/libgccjit.map
@@ -289,3 +289,8 @@ LIBGCCJIT_ABI_27 {
   global:
     gcc_jit_context_new_sizeof;
 } LIBGCCJIT_ABI_26;
+
+LIBGCCJIT_ABI_28 {
+  global:
+    gcc_jit_context_new_array_type_unsigned_long;
+} LIBGCCJIT_ABI_27;
diff --git a/gcc/testsuite/jit.dg/all-non-failing-tests.h b/gcc/testsuite/jit.dg/all-non-failing-tests.h
index 14a0a321550..223d98bcbc4 100644
--- a/gcc/testsuite/jit.dg/all-non-failing-tests.h
+++ b/gcc/testsuite/jit.dg/all-non-failing-tests.h
@@ -66,6 +66,13 @@
 #undef create_code
 #undef verify_code
 
+/* test-arrays-unsigned-long.c */
+#define create_code create_code_arrays_unsigned_long
+#define verify_code verify_code_arrays_unsigned_long
+#include "test-arrays-unsigned-long.c"
+#undef create_code
+#undef verify_code
+
 /* test-autovectorize.c */
 #define create_code create_code_autovectorize
 #define verify_code verify_code_autovectorize
@@ -461,6 +468,9 @@ const struct testcase testcases[] = {
   {"arrays",
    create_code_arrays,
    verify_code_arrays},
+  {"arrays-unsigned-long",
+   create_code_arrays_unsigned_long,
+   verify_code_arrays_unsigned_long},
   {"autovectorize",
    create_code_autovectorize,
    verify_code_autovectorize},
diff --git a/gcc/testsuite/jit.dg/test-arrays-unsigned-long.c b/gcc/testsuite/jit.dg/test-arrays-unsigned-long.c
new file mode 100644
index 00000000000..0a82c7046ea
--- /dev/null
+++ b/gcc/testsuite/jit.dg/test-arrays-unsigned-long.c
@@ -0,0 +1,165 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <stddef.h>
+
+#include "libgccjit.h"
+
+#include "harness.h"
+
+#define ARRAY_SIZE (4)
+
+/* Verify that struct layout works properly when adding an array field.  */
+struct array_holder2
+{
+  float m_before;
+  int m_ints[ARRAY_SIZE];
+  float m_after;
+};
+
+void
+create_code (gcc_jit_context *ctxt, void *user_data)
+{
+  /* Let's try to inject the equivalent of:
+
+     void
+     test_array_unsigned_long (struct array_holder2 *ah)
+     {
+	ah->m_before = 4.0f;
+	for i in 0 to (ARRAY_SIZE - 1):
+	  ah->m_ints[i] = (i * i);
+	ah->m_after = 2.0f;
+     }
+  */
+  gcc_jit_type *void_type =
+    gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_VOID);
+  gcc_jit_type *float_type =
+    gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_FLOAT);
+  gcc_jit_type *int_type =
+    gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_INT);
+
+  gcc_jit_field *field_m_before =
+    gcc_jit_context_new_field (ctxt, NULL, float_type, "m_before");
+  gcc_jit_field *field_m_ints =
+    gcc_jit_context_new_field (
+    ctxt, NULL,
+    gcc_jit_context_new_array_type_unsigned_long (ctxt, NULL, int_type, ARRAY_SIZE),
+    "m_ints");
+  gcc_jit_field *field_m_after =
+    gcc_jit_context_new_field (ctxt, NULL, float_type, "m_after");
+
+  gcc_jit_field *fields[] = {
+    field_m_before,
+    field_m_ints,
+    field_m_after,
+  };
+
+  gcc_jit_struct *struct_type =
+    gcc_jit_context_new_struct_type (
+      ctxt,
+      NULL,
+      "array_holder2",
+      3, fields);
+
+  gcc_jit_type *struct_ptr_type =
+    gcc_jit_type_get_pointer (gcc_jit_struct_as_type (struct_type));
+
+  /* Build the test_fn.  */
+  gcc_jit_param *param_ah =
+    gcc_jit_context_new_param (ctxt, NULL, struct_ptr_type, "ah");
+  gcc_jit_function *func =
+    gcc_jit_context_new_function (ctxt, NULL,
+				  GCC_JIT_FUNCTION_EXPORTED,
+				  void_type,
+				  "test_array_unsigned_long",
+				  1, &param_ah,
+				  0);
+
+  gcc_jit_block *initial = gcc_jit_function_new_block (func, "initial");
+  gcc_jit_block *loop_test = gcc_jit_function_new_block (func, "loop_test");
+  gcc_jit_block *loop_body = gcc_jit_function_new_block (func, "loop_body");
+  gcc_jit_block *final = gcc_jit_function_new_block (func, "final");
+
+  /* "ah->m_before = 4.0f;" */
+  gcc_jit_block_add_assignment (
+    initial, NULL,
+    gcc_jit_rvalue_dereference_field (
+      gcc_jit_param_as_rvalue (param_ah), NULL, field_m_before),
+    gcc_jit_context_new_rvalue_from_int (ctxt, float_type, 4));
+
+  gcc_jit_block_add_comment (initial, NULL,
+			     "for i in 0 to (ARRAY_SIZE - 1):");
+  gcc_jit_lvalue *i =
+    gcc_jit_function_new_local (func, NULL, int_type, "i");
+  gcc_jit_block_add_assignment (initial, NULL,
+      i,
+      gcc_jit_context_zero (ctxt, int_type));
+
+  gcc_jit_block_end_with_jump (initial, NULL, loop_test);
+
+  gcc_jit_block_end_with_conditional (loop_test, NULL,
+    gcc_jit_context_new_comparison (
+      ctxt, NULL,
+      GCC_JIT_COMPARISON_LT,
+      gcc_jit_lvalue_as_rvalue (i),
+      gcc_jit_context_new_rvalue_from_int (ctxt, int_type, ARRAY_SIZE)),
+    loop_body,
+    final);
+
+  gcc_jit_block_add_comment (loop_body, NULL, "ah->m_ints[i] = (i * i);");
+  gcc_jit_block_add_assignment (
+    loop_body, NULL,
+    gcc_jit_context_new_array_access (
+      ctxt, NULL,
+      gcc_jit_lvalue_as_rvalue (gcc_jit_rvalue_dereference_field (
+	gcc_jit_param_as_rvalue (param_ah),
+	NULL,
+	field_m_ints)),
+      gcc_jit_lvalue_as_rvalue (i)),
+    gcc_jit_context_new_binary_op (
+      ctxt, NULL,
+      GCC_JIT_BINARY_OP_MULT,
+      int_type,
+      gcc_jit_lvalue_as_rvalue (i),
+      gcc_jit_lvalue_as_rvalue (i)));
+
+  /* "i++" */
+  gcc_jit_block_add_assignment_op (
+    loop_body, NULL,
+    i,
+    GCC_JIT_BINARY_OP_PLUS,
+    gcc_jit_context_one (ctxt, int_type));
+
+  gcc_jit_block_end_with_jump (loop_body, NULL, loop_test);
+
+ /* ah->m_after = 2.0f; */
+  gcc_jit_block_add_assignment (
+    final, NULL,
+    gcc_jit_rvalue_dereference_field (
+      gcc_jit_param_as_rvalue (param_ah), NULL, field_m_after),
+    gcc_jit_context_new_rvalue_from_int (ctxt, float_type, 2));
+  gcc_jit_block_end_with_void_return (final, NULL);
+
+}
+
+void
+verify_code (gcc_jit_context *ctxt, gcc_jit_result *result)
+{
+  typedef void (*fn_type) (struct array_holder2 *ah);
+
+  CHECK_NON_NULL (result);
+  fn_type test_array_unsigned_long =
+    (fn_type)gcc_jit_result_get_code (result, "test_array_unsigned_long");
+  CHECK_NON_NULL (test_array_unsigned_long);
+
+  struct array_holder2 ah;
+  memset (&ah, 0xf0, sizeof (ah));
+
+  test_array_unsigned_long (&ah);
+  CHECK_VALUE (ah.m_before, 4.0f);
+  CHECK_VALUE (ah.m_ints[0], 0);
+  CHECK_VALUE (ah.m_ints[1], 1);
+  CHECK_VALUE (ah.m_ints[2], 4);
+  CHECK_VALUE (ah.m_ints[3], 9);
+  CHECK_VALUE (ah.m_after, 2.0f);
+
+}
-- 
2.43.0


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

end of thread, other threads:[~2024-02-23 14:56 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-12-07 22:29 [PATCH] libgccjit: Make new_array_type take unsigned long Antoni Boucher
2023-12-08  1:04 ` David Malcolm
2024-02-22  0:45   ` Antoni Boucher
2024-02-23 14:55     ` Antoni Boucher

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