public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [PATCH v2 0/2] RISC-V: Introduce new architecture extension test macros
@ 2021-01-07  9:55 Kito Cheng
  2021-01-07  9:55 ` [PATCH v2 1/2] RISC-V: Move class riscv_subset_list and riscv_subset_t to riscv-protos.h Kito Cheng
                   ` (2 more replies)
  0 siblings, 3 replies; 5+ messages in thread
From: Kito Cheng @ 2021-01-07  9:55 UTC (permalink / raw)
  To: gcc-patches, kito.cheng, jimw

This patch set introduce new set of architecture extension test macros
which is accept on riscv-c-api-doc[1] recently.

The motivation of this scheme is have an unify naming scheme for
extension macro and add the capability to checking version.

V2 Changes:
- Fix MacOS build issue.
- Create new header file: riscv-subset.h

[1] https://github.com/riscv/riscv-c-api-doc/blob/master/riscv-c-api.md#architecture-extension-test-macro



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

* [PATCH v2 1/2] RISC-V: Move class riscv_subset_list and riscv_subset_t to riscv-protos.h
  2021-01-07  9:55 [PATCH v2 0/2] RISC-V: Introduce new architecture extension test macros Kito Cheng
@ 2021-01-07  9:55 ` Kito Cheng
  2021-01-07  9:55 ` [PATCH v2 2/2] RISC-V: Implement new style of architecture extension test macros Kito Cheng
  2021-01-07 19:48 ` [PATCH v2 0/2] RISC-V: Introduce new " Jim Wilson
  2 siblings, 0 replies; 5+ messages in thread
From: Kito Cheng @ 2021-01-07  9:55 UTC (permalink / raw)
  To: gcc-patches, kito.cheng, jimw; +Cc: Kito Cheng

Pre-work of new style of architecture extension test macros, we need the
list used in `config/riscv/riscv-c.c`, so those struct/class declaration
must move to header file rather than local C file.

gcc/ChangeLog

	* common/config/riscv/riscv-common.c (RISCV_DONT_CARE_VERSION):
	Move to riscv-subset.h.
	(struct riscv_subset_t): Ditto.
	(class riscv_subset_list): Ditto.
	* config/riscv/riscv-subset.h (RISCV_DONT_CARE_VERSION): Move
	from riscv-common.c.
	(struct riscv_subset_t): Ditto.
	(class riscv_subset_list): Ditto.
	* config/riscv/t-riscv ($(common_out_file)): Add file
	dependency.
---
 gcc/common/config/riscv/riscv-common.c | 67 +------------------
 gcc/config/riscv/riscv-subset.h        | 90 ++++++++++++++++++++++++++
 gcc/config/riscv/t-riscv               |  4 +-
 3 files changed, 94 insertions(+), 67 deletions(-)
 create mode 100644 gcc/config/riscv/riscv-subset.h

diff --git a/gcc/common/config/riscv/riscv-common.c b/gcc/common/config/riscv/riscv-common.c
index 7b75114421d..934c716a2e8 100644
--- a/gcc/common/config/riscv/riscv-common.c
+++ b/gcc/common/config/riscv/riscv-common.c
@@ -30,22 +30,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "flags.h"
 #include "diagnostic-core.h"
 #include "config/riscv/riscv-protos.h"
-
-#define RISCV_DONT_CARE_VERSION -1
-
-/* Subset info.  */
-struct riscv_subset_t
-{
-  riscv_subset_t ();
-
-  std::string name;
-  int major_version;
-  int minor_version;
-  struct riscv_subset_t *next;
-
-  bool explicit_version_p;
-  bool implied_p;
-};
+#include "config/riscv/riscv-subset.h"
 
 /* Type for implied ISA info.  */
 struct riscv_implied_info_t
@@ -123,56 +108,6 @@ static const riscv_cpu_info riscv_cpu_tables[] =
     {NULL, NULL, NULL}
 };
 
-/* Subset list.  */
-class riscv_subset_list
-{
-private:
-  /* Original arch string.  */
-  const char *m_arch;
-
-  /* Location of arch string, used for report error.  */
-  location_t m_loc;
-
-  /* Head of subset info list.  */
-  riscv_subset_t *m_head;
-
-  /* Tail of subset info list.  */
-  riscv_subset_t *m_tail;
-
-  /* X-len of m_arch. */
-  unsigned m_xlen;
-
-  riscv_subset_list (const char *, location_t);
-
-  const char *parsing_subset_version (const char *, const char *, unsigned *,
-				      unsigned *, bool, bool *);
-
-  const char *parse_std_ext (const char *);
-
-  const char *parse_multiletter_ext (const char *, const char *,
-				     const char *);
-
-  void handle_implied_ext (riscv_subset_t *);
-
-public:
-  ~riscv_subset_list ();
-
-  void add (const char *, int, int, bool, bool);
-
-  void add (const char *, bool);
-
-  riscv_subset_t *lookup (const char *,
-			  int major_version = RISCV_DONT_CARE_VERSION,
-			  int minor_version = RISCV_DONT_CARE_VERSION) const;
-
-  std::string to_string (bool) const;
-
-  unsigned xlen() const {return m_xlen;};
-
-  static riscv_subset_list *parse (const char *, location_t);
-
-};
-
 static const char *riscv_supported_std_ext (void);
 
 static riscv_subset_list *current_subset_list = NULL;
diff --git a/gcc/config/riscv/riscv-subset.h b/gcc/config/riscv/riscv-subset.h
new file mode 100644
index 00000000000..ae7401ac0c4
--- /dev/null
+++ b/gcc/config/riscv/riscv-subset.h
@@ -0,0 +1,90 @@
+/* Definition of data structure of RISC-V subset for GNU compiler.
+   Copyright (C) 2011-2021 Free Software Foundation, Inc.
+   Contributed by Andrew Waterman (andrew@sifive.com).
+   Based on MIPS target for GNU compiler.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 3, or (at your option)
+any later version.
+
+GCC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3.  If not see
+<http://www.gnu.org/licenses/>.  */
+
+#ifndef GCC_RISCV_SUBSET_H
+#define GCC_RISCV_SUBSET_H
+
+#define RISCV_DONT_CARE_VERSION -1
+
+/* Subset info.  */
+struct riscv_subset_t
+{
+  riscv_subset_t ();
+
+  std::string name;
+  int major_version;
+  int minor_version;
+  struct riscv_subset_t *next;
+
+  bool explicit_version_p;
+  bool implied_p;
+};
+
+/* Subset list.  */
+class riscv_subset_list
+{
+private:
+  /* Original arch string.  */
+  const char *m_arch;
+
+  /* Location of arch string, used for report error.  */
+  location_t m_loc;
+
+  /* Head of subset info list.  */
+  riscv_subset_t *m_head;
+
+  /* Tail of subset info list.  */
+  riscv_subset_t *m_tail;
+
+  /* X-len of m_arch. */
+  unsigned m_xlen;
+
+  riscv_subset_list (const char *, location_t);
+
+  const char *parsing_subset_version (const char *, const char *, unsigned *,
+				      unsigned *, bool, bool *);
+
+  const char *parse_std_ext (const char *);
+
+  const char *parse_multiletter_ext (const char *, const char *,
+				     const char *);
+
+  void handle_implied_ext (riscv_subset_t *);
+
+public:
+  ~riscv_subset_list ();
+
+  void add (const char *, int, int, bool, bool);
+
+  void add (const char *, bool);
+
+  riscv_subset_t *lookup (const char *,
+			  int major_version = RISCV_DONT_CARE_VERSION,
+			  int minor_version = RISCV_DONT_CARE_VERSION) const;
+
+  std::string to_string (bool) const;
+
+  unsigned xlen () const {return m_xlen;};
+
+  static riscv_subset_list *parse (const char *, location_t);
+};
+
+#endif /* ! GCC_RISCV_SUBSET_H */
diff --git a/gcc/config/riscv/t-riscv b/gcc/config/riscv/t-riscv
index 702767c1736..1215ea8b734 100644
--- a/gcc/config/riscv/t-riscv
+++ b/gcc/config/riscv/t-riscv
@@ -25,4 +25,6 @@ riscv-shorten-memrefs.o: $(srcdir)/config/riscv/riscv-shorten-memrefs.c
 
 PASSES_EXTRA += $(srcdir)/config/riscv/riscv-passes.def
 
-$(common_out_file): $(srcdir)/config/riscv/riscv-cores.def
+$(common_out_file): $(srcdir)/config/riscv/riscv-cores.def \
+    $(srcdir)/config/riscv/riscv-protos.h \
+    $(srcdir)/config/riscv/riscv-subset.h
-- 
2.30.0


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

* [PATCH v2 2/2] RISC-V: Implement new style of architecture extension test macros.
  2021-01-07  9:55 [PATCH v2 0/2] RISC-V: Introduce new architecture extension test macros Kito Cheng
  2021-01-07  9:55 ` [PATCH v2 1/2] RISC-V: Move class riscv_subset_list and riscv_subset_t to riscv-protos.h Kito Cheng
@ 2021-01-07  9:55 ` Kito Cheng
  2021-01-07 19:48 ` [PATCH v2 0/2] RISC-V: Introduce new " Jim Wilson
  2 siblings, 0 replies; 5+ messages in thread
From: Kito Cheng @ 2021-01-07  9:55 UTC (permalink / raw)
  To: gcc-patches, kito.cheng, jimw; +Cc: Kito Cheng

- This patch introduce new set of architecture extension test macros
  which is accept on riscv-c-api-doc recently.
  - https://github.com/riscv/riscv-c-api-doc/blob/master/riscv-c-api.md#architecture-extension-test-macro

- We will also mark deprecated for legacy architecture extension test macros
  in GCC 11, but still support that for 1 or 2 release cycles.

gcc/ChangeLog:

	* common/config/riscv/riscv-common.c (riscv_current_subset_list): New.
	* config/riscv/riscv-c.c (riscv-subset.h): New.
	(INCLUDE_STRING): Define.
	(riscv_cpu_cpp_builtins): Add new style architecture extension
	test macros.
	* config/riscv/riscv-subset.h (riscv_subset_list::begin): New.
	(riscv_subset_list::end): New.
	(riscv_current_subset_list): New.

gcc/testsuite/ChangeLog:

	* gcc.target/riscv/predef-10.c: New.
	* gcc.target/riscv/predef-11.c: New.
	* gcc.target/riscv/predef-12.c: New.
	* gcc.target/riscv/predef-13.c: New.
---
 gcc/common/config/riscv/riscv-common.c     |  5 +++
 gcc/config/riscv/riscv-c.c                 | 32 ++++++++++++++++
 gcc/config/riscv/riscv-subset.h            |  5 +++
 gcc/testsuite/gcc.target/riscv/predef-10.c | 43 ++++++++++++++++++++++
 gcc/testsuite/gcc.target/riscv/predef-11.c | 43 ++++++++++++++++++++++
 gcc/testsuite/gcc.target/riscv/predef-12.c | 43 ++++++++++++++++++++++
 gcc/testsuite/gcc.target/riscv/predef-13.c | 43 ++++++++++++++++++++++
 7 files changed, 214 insertions(+)
 create mode 100644 gcc/testsuite/gcc.target/riscv/predef-10.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/predef-11.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/predef-12.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/predef-13.c

diff --git a/gcc/common/config/riscv/riscv-common.c b/gcc/common/config/riscv/riscv-common.c
index 934c716a2e8..b3f5c07c819 100644
--- a/gcc/common/config/riscv/riscv-common.c
+++ b/gcc/common/config/riscv/riscv-common.c
@@ -112,6 +112,11 @@ static const char *riscv_supported_std_ext (void);
 
 static riscv_subset_list *current_subset_list = NULL;
 
+const riscv_subset_list *riscv_current_subset_list ()
+{
+  return current_subset_list;
+}
+
 riscv_subset_t::riscv_subset_t ()
   : name (), major_version (0), minor_version (0), next (NULL),
     explicit_version_p (false), implied_p (false)
diff --git a/gcc/config/riscv/riscv-c.c b/gcc/config/riscv/riscv-c.c
index 8c52f74b6b1..efd4a61ea29 100644
--- a/gcc/config/riscv/riscv-c.c
+++ b/gcc/config/riscv/riscv-c.c
@@ -20,12 +20,14 @@ along with GCC; see the file COPYING3.  If not see
 
 #define IN_TARGET_CODE 1
 
+#define INCLUDE_STRING
 #include "config.h"
 #include "system.h"
 #include "coretypes.h"
 #include "tm.h"
 #include "c-family/c-common.h"
 #include "cpplib.h"
+#include "riscv-subset.h"
 
 #define builtin_define(TXT) cpp_define (pfile, TXT)
 
@@ -101,4 +103,34 @@ riscv_cpu_cpp_builtins (cpp_reader *pfile)
       break;
 
     }
+
+  /* Define architecture extension test macros.  */
+  builtin_define_with_int_value ("__riscv_arch_test", 1);
+
+  const riscv_subset_list *subset_list = riscv_current_subset_list ();
+  size_t max_ext_len = 0;
+
+  /* Figure out the max length of extension name for reserving buffer.   */
+  for (const riscv_subset_t *subset = subset_list->begin ();
+       subset != subset_list->end ();
+       subset = subset->next)
+    max_ext_len = MAX (max_ext_len, subset->name.length ());
+
+  char *buf = (char *)alloca (max_ext_len + 10 /* For __riscv_ and '\0'.  */);
+
+  for (const riscv_subset_t *subset = subset_list->begin ();
+       subset != subset_list->end ();
+       subset = subset->next)
+    {
+      int version_value = (subset->major_version * 1000000)
+			   + (subset->minor_version * 1000);
+      /* Special rule for zicsr and zifencei, it's used for ISA spec 2.2 or
+	 earlier.  */
+      if ((subset->name == "zicsr" || subset->name == "zifencei")
+	  && version_value == 0)
+	version_value = 2000000;
+
+      sprintf (buf, "__riscv_%s", subset->name.c_str ());
+      builtin_define_with_int_value (buf, version_value);
+    }
 }
diff --git a/gcc/config/riscv/riscv-subset.h b/gcc/config/riscv/riscv-subset.h
index ae7401ac0c4..793655a01f2 100644
--- a/gcc/config/riscv/riscv-subset.h
+++ b/gcc/config/riscv/riscv-subset.h
@@ -85,6 +85,11 @@ public:
   unsigned xlen () const {return m_xlen;};
 
   static riscv_subset_list *parse (const char *, location_t);
+
+  const riscv_subset_t *begin () const {return m_head;};
+  const riscv_subset_t *end () const {return NULL;};
 };
 
+extern const riscv_subset_list *riscv_current_subset_list (void);
+
 #endif /* ! GCC_RISCV_SUBSET_H */
diff --git a/gcc/testsuite/gcc.target/riscv/predef-10.c b/gcc/testsuite/gcc.target/riscv/predef-10.c
new file mode 100644
index 00000000000..7c447bfb08d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/predef-10.c
@@ -0,0 +1,43 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -march=rv32i2p0 -mabi=ilp32 -mcmodel=medlow -misa-spec=2.2" } */
+
+int main () {
+
+#ifndef __riscv_arch_test
+#error "__riscv_arch_test"
+#endif
+
+#if __riscv_xlen != 32
+#error "__riscv_xlen"
+#endif
+
+#if !defined(__riscv_i) || (__riscv_i != (2 * 1000 * 1000))
+#error "__riscv_i"
+#endif
+
+#if defined(__riscv_c)
+#error "__riscv_c"
+#endif
+
+#if defined(__riscv_e)
+#error "__riscv_e"
+#endif
+
+#if defined(__riscv_a)
+#error "__riscv_a"
+#endif
+
+#if defined(__riscv_m)
+#error "__riscv_m"
+#endif
+
+#if defined(__riscv_f)
+#error "__riscv_f"
+#endif
+
+#if defined(__riscv_d)
+#error "__riscv_d"
+#endif
+
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.target/riscv/predef-11.c b/gcc/testsuite/gcc.target/riscv/predef-11.c
new file mode 100644
index 00000000000..80f48113dfa
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/predef-11.c
@@ -0,0 +1,43 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -march=rv64gc -mabi=lp64 -mcmodel=medlow -misa-spec=2.2" } */
+
+int main () {
+
+#ifndef __riscv_arch_test
+#error "__riscv_arch_test"
+#endif
+
+#if __riscv_xlen != 64
+#error "__riscv_xlen"
+#endif
+
+#if !defined(__riscv_i) || (__riscv_i != (2 * 1000 * 1000))
+#error "__riscv_i"
+#endif
+
+#if !defined(__riscv_c) || (__riscv_c != (2 * 1000 * 1000))
+#error "__riscv_c"
+#endif
+
+#if defined(__riscv_e)
+#error "__riscv_e"
+#endif
+
+#if !defined(__riscv_a) || (__riscv_a != (2 * 1000 * 1000))
+#error "__riscv_a"
+#endif
+
+#if !defined(__riscv_m) || (__riscv_m != (2 * 1000 * 1000))
+#error "__riscv_m"
+#endif
+
+#if !defined(__riscv_f) || (__riscv_f != (2 * 1000 * 1000))
+#error "__riscv_f"
+#endif
+
+#if !defined(__riscv_d) || (__riscv_d != (2 * 1000 * 1000))
+#error "__riscv_d"
+#endif
+
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.target/riscv/predef-12.c b/gcc/testsuite/gcc.target/riscv/predef-12.c
new file mode 100644
index 00000000000..dd35dbde925
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/predef-12.c
@@ -0,0 +1,43 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -march=rv64gc -mabi=lp64 -mcmodel=medlow -misa-spec=20191213" } */
+
+int main () {
+
+#ifndef __riscv_arch_test
+#error "__riscv_arch_test"
+#endif
+
+#if __riscv_xlen != 64
+#error "__riscv_xlen"
+#endif
+
+#if !defined(__riscv_i) || (__riscv_i != (2 * 1000 * 1000 + 1 * 1000))
+#error "__riscv_i"
+#endif
+
+#if !defined(__riscv_c) || (__riscv_c != (2 * 1000 * 1000))
+#error "__riscv_c"
+#endif
+
+#if defined(__riscv_e)
+#error "__riscv_e"
+#endif
+
+#if !defined(__riscv_a) || (__riscv_a != (2 * 1000 * 1000 + 1 * 1000))
+#error "__riscv_a"
+#endif
+
+#if !defined(__riscv_m) || (__riscv_m != (2 * 1000 * 1000))
+#error "__riscv_m"
+#endif
+
+#if !defined(__riscv_f) || (__riscv_f != (2 * 1000 * 1000 + 2 * 1000))
+#error "__riscv_f"
+#endif
+
+#if !defined(__riscv_d) || (__riscv_d != (2 * 1000 * 1000 + 2 * 1000))
+#error "__riscv_d"
+#endif
+
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.target/riscv/predef-13.c b/gcc/testsuite/gcc.target/riscv/predef-13.c
new file mode 100644
index 00000000000..95cf0012408
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/predef-13.c
@@ -0,0 +1,43 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -march=rv32e -mabi=ilp32e -mcmodel=medlow -misa-spec=2.2" } */
+
+int main () {
+
+#ifndef __riscv_arch_test
+#error "__riscv_arch_test"
+#endif
+
+#if __riscv_xlen != 32
+#error "__riscv_xlen"
+#endif
+
+#if defined(__riscv_i)
+#error "__riscv_i"
+#endif
+
+#if defined(__riscv_c)
+#error "__riscv_c"
+#endif
+
+#if !defined(__riscv_e) || (__riscv_e != (1 * 1000 * 1000 + 9 * 1000))
+#error "__riscv_e"
+#endif
+
+#if defined(__riscv_a)
+#error "__riscv_a"
+#endif
+
+#if defined(__riscv_m)
+#error "__riscv_m"
+#endif
+
+#if defined(__riscv_f)
+#error "__riscv_f"
+#endif
+
+#if defined(__riscv_d)
+#error "__riscv_d"
+#endif
+
+  return 0;
+}
-- 
2.30.0


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

* Re: [PATCH v2 0/2] RISC-V: Introduce new architecture extension test macros
  2021-01-07  9:55 [PATCH v2 0/2] RISC-V: Introduce new architecture extension test macros Kito Cheng
  2021-01-07  9:55 ` [PATCH v2 1/2] RISC-V: Move class riscv_subset_list and riscv_subset_t to riscv-protos.h Kito Cheng
  2021-01-07  9:55 ` [PATCH v2 2/2] RISC-V: Implement new style of architecture extension test macros Kito Cheng
@ 2021-01-07 19:48 ` Jim Wilson
  2021-01-08  3:34   ` Kito Cheng
  2 siblings, 1 reply; 5+ messages in thread
From: Jim Wilson @ 2021-01-07 19:48 UTC (permalink / raw)
  To: Kito Cheng; +Cc: GCC Patches, Kito Cheng

On Thu, Jan 7, 2021 at 1:55 AM Kito Cheng <kito.cheng@sifive.com> wrote:

> This patch set introduce new set of architecture extension test macros
> which is accept on riscv-c-api-doc[1] recently.
>
> The motivation of this scheme is have an unify naming scheme for
> extension macro and add the capability to checking version.
>
> V2 Changes:
> - Fix MacOS build issue.
> - Create new header file: riscv-subset.h
>

This patch series looks good to me.

Jim

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

* Re: [PATCH v2 0/2] RISC-V: Introduce new architecture extension test macros
  2021-01-07 19:48 ` [PATCH v2 0/2] RISC-V: Introduce new " Jim Wilson
@ 2021-01-08  3:34   ` Kito Cheng
  0 siblings, 0 replies; 5+ messages in thread
From: Kito Cheng @ 2021-01-08  3:34 UTC (permalink / raw)
  To: Jim Wilson; +Cc: Kito Cheng, GCC Patches

Committed, thanks :)

On Fri, Jan 8, 2021 at 3:49 AM Jim Wilson <jimw@sifive.com> wrote:
>
> On Thu, Jan 7, 2021 at 1:55 AM Kito Cheng <kito.cheng@sifive.com> wrote:
>
> > This patch set introduce new set of architecture extension test macros
> > which is accept on riscv-c-api-doc[1] recently.
> >
> > The motivation of this scheme is have an unify naming scheme for
> > extension macro and add the capability to checking version.
> >
> > V2 Changes:
> > - Fix MacOS build issue.
> > - Create new header file: riscv-subset.h
> >
>
> This patch series looks good to me.
>
> Jim

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

end of thread, other threads:[~2021-01-08  3:34 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-01-07  9:55 [PATCH v2 0/2] RISC-V: Introduce new architecture extension test macros Kito Cheng
2021-01-07  9:55 ` [PATCH v2 1/2] RISC-V: Move class riscv_subset_list and riscv_subset_t to riscv-protos.h Kito Cheng
2021-01-07  9:55 ` [PATCH v2 2/2] RISC-V: Implement new style of architecture extension test macros Kito Cheng
2021-01-07 19:48 ` [PATCH v2 0/2] RISC-V: Introduce new " Jim Wilson
2021-01-08  3:34   ` Kito Cheng

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