From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail-wr1-x42b.google.com (mail-wr1-x42b.google.com [IPv6:2a00:1450:4864:20::42b]) by sourceware.org (Postfix) with ESMTPS id 1A73D3858D28; Tue, 29 Aug 2023 15:16:09 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 1A73D3858D28 Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=gmail.com Received: by mail-wr1-x42b.google.com with SMTP id ffacd0b85a97d-31c3df710bdso3590667f8f.1; Tue, 29 Aug 2023 08:16:09 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20221208; t=1693322168; x=1693926968; h=content-transfer-encoding:cc:to:subject:message-id:date:from :in-reply-to:references:mime-version:from:to:cc:subject:date :message-id:reply-to; bh=gXCT1WbDYJHLDz31KA9OURZ+KnWZroBYX7NefAg+SBM=; b=Fcazi+YQYl7CyOoq9gV8qaYhe244c495hvvgiD0Bdzdc4w6iTpoY0t5JHYcWuCajkx xS3E9ZdTLa1A8NstXF7JZGQ5mxy5Xp8Un77geCbXrrVqwCxoHp49jQi+lGkTJRQ3h+lD jEPuRKhiQWXoQLvWUzNVWuYjNX2K3Z1jkRXGL/nLND67djfN5n01YDXC6bEYowEeAbLF O8uNOq98aQotbtRTi11lyLbNnmk/mYJB6lPGEx8gJqtXg2QKuk1bbxh6dxDL66vILXu8 PWqHxKYoddyr+tjWegJ4tbIgCCFfxgPl5vM0pQkGA6Fp8qaXNZmzVNmnEZItxq7RT7Nb PK9g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1693322168; x=1693926968; h=content-transfer-encoding:cc:to:subject:message-id:date:from :in-reply-to:references:mime-version:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=gXCT1WbDYJHLDz31KA9OURZ+KnWZroBYX7NefAg+SBM=; b=lAAJ30WWn37XfnoK/MZ6G5KIQpFNTuiwvyzFgbhUbo4ksnyMdGSGTPDlu+yDUhD+or rk6P3hQAroZGimCH+ghA9Zizm59EHEcuHIX+YBoMgUxJO9SayzUF9TCCdAWPIJBrEbVj IHzHZvbceKo7Fikn37gL/E6sUrpVQ9S0zsybxZ7Q9y9IZ3Smmf9AFId98DP4JscqKhRV DYPv7wi/qR7fjYK1ahiCYopGtSu04xDd3kzmWBG2uEzdjmTLtoziBL6SfyxGmwuzhwXG 9gRAe2ICfs63bggbExPFNqT1oh77G9abqvwOaFLopskwwEpXb/F5yGYS1lu3d9hWWQ7Y MxCw== X-Gm-Message-State: AOJu0Yz2oD3QCVPoorS3NVyU9wjr3nManaon0rp5CAHO3BHzGNtHG8nP TDEvuL6Sv1UrVtlT6r4dcy+H1uwrOEVJkb9NkVM= X-Google-Smtp-Source: AGHT+IFpq0t6OCDy9vf7ub7F7CmLuqOTk+LAW7TsYFcQgvPU4mQs7ThnU45ZUx90EWq8SmUm/j5Tjy6swnW7b2FO7iY= X-Received: by 2002:adf:f3cd:0:b0:317:3f64:4901 with SMTP id g13-20020adff3cd000000b003173f644901mr19691214wrp.41.1693322167419; Tue, 29 Aug 2023 08:16:07 -0700 (PDT) MIME-Version: 1.0 References: <059ffebd230df2dbbac3f138ec85016bb7a7306a.camel@redhat.com> In-Reply-To: From: Guillaume Gomez Date: Tue, 29 Aug 2023 17:15:55 +0200 Message-ID: Subject: Re: [PATCH] libgccjit: Add support for `restrict` attribute on function parameters To: Antoni Boucher Cc: David Malcolm , gcc-patches@gcc.gnu.org, jit@gcc.gnu.org Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable X-Spam-Status: No, score=-9.0 required=5.0 tests=BAYES_00,DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,FREEMAIL_FROM,GIT_PATCH_0,RCVD_IN_DNSWL_NONE,SPF_HELO_NONE,SPF_PASS,TXREP autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org List-Id: We finished the investigation and found out the issue: when passing arguments by value to functions, rustc still provides "NoAlias" as attribute to the argument whereas it should never be passed in this case. Luckily for us, in case the argument is a function pointer coming from a struct field, it crashes GCC, which is what allowed us to figure out about this. A code which reproduces this bug: ``` use std::mem; #[repr(C)] pub struct Buffer { data: *mut u8, len: usize, drop: extern "C" fn(Buffer), } impl Default for Buffer { #[inline] fn default() -> Self { Self::from(vec![]) } } impl Buffer { #[inline] pub fn new() -> Self { Self::default() } #[inline] pub fn push(&mut self, v: u8) {} } impl From> for Buffer { fn from(mut v: Vec) -> Self { let (data, len) =3D (v.as_mut_ptr(), v.len()); mem::forget(v); extern "C" fn drop(b: Buffer) {} Buffer { data, len, drop } } } fn main() { let mut buffer =3D Buffer::new(); } ``` So in short: the patch in the previous mail which added this check: ``` RETURN_NULL_IF_FAIL (type->is_pointer (), NULL, NULL, "not a pointer type")= ; ``` is correct and ready. We fixed the bug on our side in https://github.com/rust-lang/rustc_codegen_gcc/pull/312. For more information about the "ByValue" attributes issue, there were some discussions about it in LLVM: * https://lists.llvm.org/pipermail/llvm-commits/Week-of-Mon-20171218/51206= 6.html * https://reviews.llvm.org/D40118 Le ven. 25 ao=C3=BBt 2023 =C3=A0 22:47, Guillaume Gomez a =C3=A9crit : > > After more investigations, it seems like the fault was on our side as > we were calling `gcc_jit_type_get_restrict` on types that weren't > pointers. > I added a check for that in `gcc_jit_type_get_restrict` directly as well. > > We will continue our investigation to be sure we didn't miss anything. > > Le mar. 22 ao=C3=BBt 2023 =C3=A0 17:26, Antoni Boucher = a =C3=A9crit : > > > > Since the tests in the PR for rustc_codegen_gcc > > (https://github.com/rust-lang/rustc_codegen_gcc/pull/312) currently > > fails, let's wait a bit before merging the patch, in case it would need > > some fixes. > > > > On Thu, 2023-08-17 at 20:09 +0200, Guillaume Gomez via Jit wrote: > > > Quick question: do you plan to make the merge or should I ask Antoni? > > > > > > Le jeu. 17 ao=C3=BBt 2023 =C3=A0 17:59, Guillaume Gomez > > > > > > a =C3=A9crit : > > > > > > > Thanks for the review! > > > > > > > > Le jeu. 17 ao=C3=BBt 2023 =C3=A0 17:50, David Malcolm a > > > > =C3=A9crit > > > > : > > > > > > > > > > On Thu, 2023-08-17 at 17:41 +0200, Guillaume Gomez wrote: > > > > > > And now I just discovered that a lot of commits from Antoni's > > > > > > fork > > > > > > haven't been sent upstream which is why the ABI count is so > > > > > > high in > > > > > > his repository. Fixed that as well. > > > > > > > > > > Thanks for the updated patch; I was about to comment on that. > > > > > > > > > > This version is good for gcc trunk. > > > > > > > > > > Dave > > > > > > > > > > > > > > > > > Le jeu. 17 ao=C3=BBt 2023 =C3=A0 17:26, Guillaume Gomez > > > > > > a =C3=A9crit : > > > > > > > > > > > > > > Antoni spot a typo I made: > > > > > > > > > > > > > > I added `LIBGCCJIT_HAVE_gcc_jit_type_get_size` instead of > > > > > > > `LIBGCCJIT_HAVE_gcc_jit_type_get_restrict`. Fixed in this > > > > > > > patch, > > > > > > > sorry > > > > > > > for the noise. > > > > > > > > > > > > > > Le jeu. 17 ao=C3=BBt 2023 =C3=A0 11:30, Guillaume Gomez > > > > > > > a =C3=A9crit : > > > > > > > > > > > > > > > > Hi Dave, > > > > > > > > > > > > > > > > > What kind of testing has the patch had? (e.g. did you run > > > > > > > > > "make > > > > > > > > > check- > > > > > > > > > jit" ? Has this been in use on real Rust code?) > > > > > > > > > > > > > > > > I tested it as Rust backend directly on this code: > > > > > > > > > > > > > > > > ``` > > > > > > > > pub fn foo(a: &mut i32, b: &mut i32, c: &i32) { > > > > > > > > *a +=3D *c; > > > > > > > > *b +=3D *c; > > > > > > > > } > > > > > > > > ``` > > > > > > > > > > > > > > > > I ran it with `rustc` (and the GCC backend) with the > > > > > > > > following > > > > > > > > flags: > > > > > > > > `-C link-args=3D-lc --emit=3Dasm -O --crate-type=3Dlib` whi= ch > > > > > > > > gave the > > > > > > > > diff > > > > > > > > you can see in the attached file. Explanations: the diff on > > > > > > > > the > > > > > > > > right > > > > > > > > has the `__restrict__` attribute used whereas on the left > > > > > > > > it is > > > > > > > > the > > > > > > > > current version where we don't handle it. > > > > > > > > > > > > > > > > As for C testing, I used this code: > > > > > > > > > > > > > > > > ``` > > > > > > > > void t(int *__restrict__ a, int *__restrict__ b, char > > > > > > > > *__restrict__ c) { > > > > > > > > *a +=3D *c; > > > > > > > > *b +=3D *c; > > > > > > > > } > > > > > > > > ``` > > > > > > > > > > > > > > > > (without the `__restrict__` of course when I need to have a > > > > > > > > witness > > > > > > > > ASM). I attached the diff as well, this time the file with > > > > > > > > the > > > > > > > > use of > > > > > > > > `__restrict__` in on the left. I compiled with the > > > > > > > > following > > > > > > > > flags: > > > > > > > > `-S -O3`. > > > > > > > > > > > > > > > > > Please add a feature macro: > > > > > > > > > #define LIBGCCJIT_HAVE_gcc_jit_type_get_restrict > > > > > > > > > (see the similar ones in the header). > > > > > > > > > > > > > > > > I added `LIBGCCJIT_HAVE_gcc_jit_type_get_size` and extended > > > > > > > > the > > > > > > > > documentation as well to mention the ABI change. > > > > > > > > > > > > > > > > > Please add a new ABI tag (LIBGCCJIT_ABI_25 ?), rather > > > > > > > > > than > > > > > > > > > adding this > > > > > > > > > to ABI_0. > > > > > > > > > > > > > > > > I added `LIBGCCJIT_ABI_34` as `LIBGCCJIT_ABI_33` was the > > > > > > > > last > > > > > > > > one. > > > > > > > > > > > > > > > > > This refers to a "cold attribute"; is this a vestige of a > > > > > > > > > copy- > > > > > > > > > and- > > > > > > > > > paste from a different test case? > > > > > > > > > > > > > > > > It is a vestige indeed... Missed this one. > > > > > > > > > > > > > > > > > I see that the test scans the generated assembler. Does > > > > > > > > > the > > > > > > > > > test > > > > > > > > > actually verify that restrict has an effect, or was that > > > > > > > > > another > > > > > > > > > vestige from a different test case? > > > > > > > > > > > > > > > > No, this time it's what I wanted. Please see the C diff I > > > > > > > > provided > > > > > > > > above to see that the ASM has a small diff that allowed me > > > > > > > > to > > > > > > > > confirm > > > > > > > > that the `__restrict__` attribute was correctly set. > > > > > > > > > > > > > > > > > If this test is meant to run at -O3 and thus can't be > > > > > > > > > part of > > > > > > > > > test- > > > > > > > > > combination.c, please add a comment about it to > > > > > > > > > gcc/testsuite/jit.dg/all-non-failing-tests.h (in the > > > > > > > > > alphabetical > > > > > > > > > place). > > > > > > > > > > > > > > > > Below `-O3`, this ASM difference doesn't appear > > > > > > > > unfortunately. > > > > > > > > > > > > > > > > > The patch also needs to add documentation for the new > > > > > > > > > entrypoint (in > > > > > > > > > topics/types.rst), and for the new ABI tag (in > > > > > > > > > topics/compatibility.rst). > > > > > > > > > > > > > > > > Added! > > > > > > > > > > > > > > > > > Thanks again for the patch; hope the above is > > > > > > > > > constructive > > > > > > > > > > > > > > > > It was incredibly useful! Thanks for taking time to writing > > > > > > > > down > > > > > > > > the > > > > > > > > explanations. > > > > > > > > > > > > > > > > The new patch is attached to this email. > > > > > > > > > > > > > > > > Cordially. > > > > > > > > > > > > > > > > Le jeu. 17 ao=C3=BBt 2023 =C3=A0 01:06, David Malcolm > > > > > > > > > > > > > > > > a =C3=A9crit : > > > > > > > > > > > > > > > > > > On Wed, 2023-08-16 at 22:06 +0200, Guillaume Gomez via > > > > > > > > > Jit > > > > > > > > > wrote: > > > > > > > > > > My apologies, forgot to run the commit checkers. Here's > > > > > > > > > > the > > > > > > > > > > commit > > > > > > > > > > with the errors fixed. > > > > > > > > > > > > > > > > > > > > Le mer. 16 ao=C3=BBt 2023 =C3=A0 18:32, Guillaume Gomez > > > > > > > > > > a =C3=A9crit : > > > > > > > > > > > > > > > > > > > > > > Hi, > > > > > > > > > > > > > > > > > > Hi Guillaume, thanks for the patch. > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > This patch adds the possibility to specify the > > > > > > > > > > > __restrict__ > > > > > > > > > > > attribute > > > > > > > > > > > for function parameters. It is used by the Rust GCC > > > > > > > > > > > backend. > > > > > > > > > > > > > > > > > > What kind of testing has the patch had? (e.g. did you run > > > > > > > > > "make > > > > > > > > > check- > > > > > > > > > jit" ? Has this been in use on real Rust code?) > > > > > > > > > > > > > > > > > > Overall, this patch looks close to being ready, but some > > > > > > > > > nits > > > > > > > > > below... > > > > > > > > > > > > > > > > > > [...] > > > > > > > > > > > > > > > > > > > diff --git a/gcc/jit/libgccjit.h b/gcc/jit/libgccjit.h > > > > > > > > > > index 60eaf39bff6..2e0d08a06d8 100644 > > > > > > > > > > --- a/gcc/jit/libgccjit.h > > > > > > > > > > +++ b/gcc/jit/libgccjit.h > > > > > > > > > > @@ -635,6 +635,10 @@ gcc_jit_type_get_const > > > > > > > > > > (gcc_jit_type > > > > > > > > > > *type); > > > > > > > > > > extern gcc_jit_type * > > > > > > > > > > gcc_jit_type_get_volatile (gcc_jit_type *type); > > > > > > > > > > > > > > > > > > > > +/* Given type "T", get type "restrict T". */ > > > > > > > > > > +extern gcc_jit_type * > > > > > > > > > > +gcc_jit_type_get_restrict (gcc_jit_type *type); > > > > > > > > > > + > > > > > > > > > > #define LIBGCCJIT_HAVE_SIZED_INTEGERS > > > > > > > > > > > > > > > > > > > > /* Given types LTYPE and RTYPE, return non-zero if > > > > > > > > > > they are > > > > > > > > > compatible. > > > > > > > > > > > > > > > > > > Please add a feature macro: > > > > > > > > > #define LIBGCCJIT_HAVE_gcc_jit_type_get_restrict > > > > > > > > > (see the similar ones in the header). > > > > > > > > > > > > > > > > > > > diff --git a/gcc/jit/libgccjit.map > > > > > > > > > > b/gcc/jit/libgccjit.map > > > > > > > > > > index e52de0057a5..b7289b13845 100644 > > > > > > > > > > --- a/gcc/jit/libgccjit.map > > > > > > > > > > +++ b/gcc/jit/libgccjit.map > > > > > > > > > > @@ -104,6 +104,7 @@ LIBGCCJIT_ABI_0 > > > > > > > > > > gcc_jit_type_as_object; > > > > > > > > > > gcc_jit_type_get_const; > > > > > > > > > > gcc_jit_type_get_pointer; > > > > > > > > > > + gcc_jit_type_get_restrict; > > > > > > > > > > gcc_jit_type_get_volatile; > > > > > > > > > > > > > > > > > > Please add a new ABI tag (LIBGCCJIT_ABI_25 ?), rather > > > > > > > > > than > > > > > > > > > adding this > > > > > > > > > to ABI_0. > > > > > > > > > > > > > > > > > > > diff --git a/gcc/testsuite/jit.dg/test-restrict.c > > > > > > > > > b/gcc/testsuite/jit.dg/test-restrict.c > > > > > > > > > > new file mode 100644 > > > > > > > > > > index 00000000000..4c8c4407f91 > > > > > > > > > > --- /dev/null > > > > > > > > > > +++ b/gcc/testsuite/jit.dg/test-restrict.c > > > > > > > > > > @@ -0,0 +1,77 @@ > > > > > > > > > > +/* { dg-do compile { target x86_64-*-* } } */ > > > > > > > > > > + > > > > > > > > > > +#include > > > > > > > > > > +#include > > > > > > > > > > + > > > > > > > > > > +#include "libgccjit.h" > > > > > > > > > > + > > > > > > > > > > +/* We don't want set_options() in harness.h to set -O3 > > > > > > > > > > to > > > > > > > > > > see that > > > > > > > > > the cold > > > > > > > > > > + attribute affects the optimizations. */ > > > > > > > > > > > > > > > > > > This refers to a "cold attribute"; is this a vestige of a > > > > > > > > > copy- > > > > > > > > > and- > > > > > > > > > paste from a different test case? > > > > > > > > > > > > > > > > > > I see that the test scans the generated assembler. Does > > > > > > > > > the > > > > > > > > > test > > > > > > > > > actually verify that restrict has an effect, or was that > > > > > > > > > another > > > > > > > > > vestige from a different test case? > > > > > > > > > > > > > > > > > > > +#define TEST_ESCHEWS_SET_OPTIONS > > > > > > > > > > +static void set_options (gcc_jit_context *ctxt, const > > > > > > > > > > char > > > > > > > > > > *argv0) > > > > > > > > > > +{ > > > > > > > > > > + // Set "-O3". > > > > > > > > > > + gcc_jit_context_set_int_option(ctxt, > > > > > > > > > GCC_JIT_INT_OPTION_OPTIMIZATION_LEVEL, 3); > > > > > > > > > > +} > > > > > > > > > > + > > > > > > > > > > +#define TEST_COMPILING_TO_FILE > > > > > > > > > > +#define OUTPUT_KIND GCC_JIT_OUTPUT_KIND_ASSEMBLER > > > > > > > > > > +#define OUTPUT_FILENAME "output-of-test-restrict.c.s" > > > > > > > > > > +#include "harness.h" > > > > > > > > > > + > > > > > > > > > > +void > > > > > > > > > > +create_code (gcc_jit_context *ctxt, void *user_data) > > > > > > > > > > +{ > > > > > > > > > > + /* Let's try to inject the equivalent of: > > > > > > > > > > +void t(int *__restrict__ a, int *__restrict__ b, char > > > > > > > > > > *__restrict__ > > > > > > > > > c) { > > > > > > > > > > + *a +=3D *c; > > > > > > > > > > + *b +=3D *c; > > > > > > > > > > +} > > > > > > > > > > + */ > > > > > > > > > > + gcc_jit_type *int_type =3D > > > > > > > > > > + gcc_jit_context_get_type (ctxt, > > > > > > > > > > GCC_JIT_TYPE_INT); > > > > > > > > > > + gcc_jit_type *pint_type =3D > > > > > > > > > > gcc_jit_type_get_pointer(int_type); > > > > > > > > > > + gcc_jit_type *pint_restrict_type =3D > > > > > > > > > gcc_jit_type_get_restrict(pint_type); > > > > > > > > > > + > > > > > > > > > > + gcc_jit_type *void_type =3D > > > > > > > > > > + gcc_jit_context_get_type (ctxt, > > > > > > > > > > GCC_JIT_TYPE_VOID); > > > > > > > > > > + > > > > > > > > > > + gcc_jit_param *a =3D > > > > > > > > > > + gcc_jit_context_new_param (ctxt, NULL, > > > > > > > > > pint_restrict_type, "a"); > > > > > > > > > > + gcc_jit_param *b =3D > > > > > > > > > > + gcc_jit_context_new_param (ctxt, NULL, > > > > > > > > > pint_restrict_type, "b"); > > > > > > > > > > + gcc_jit_param *c =3D > > > > > > > > > > + gcc_jit_context_new_param (ctxt, NULL, > > > > > > > > > pint_restrict_type, "c"); > > > > > > > > > > + gcc_jit_param *params[3] =3D {a, b, c}; > > > > > > > > > > + > > > > > > > > > > + gcc_jit_function *func_t =3D > > > > > > > > > > + gcc_jit_context_new_function (ctxt, NULL, > > > > > > > > > > + > > > > > > > > > > GCC_JIT_FUNCTION_EXPORTED, > > > > > > > > > > + void_type, > > > > > > > > > > + "t", > > > > > > > > > > + 3, params, > > > > > > > > > > + 0); > > > > > > > > > > + > > > > > > > > > > + gcc_jit_block *block =3D gcc_jit_function_new_blo= ck > > > > > > > > > > (func_t, > > > > > > > > > NULL); > > > > > > > > > > + > > > > > > > > > > + /* *a +=3D *c; */ > > > > > > > > > > + gcc_jit_block_add_assignment_op ( > > > > > > > > > > + block, NULL, > > > > > > > > > > + gcc_jit_rvalue_dereference > > > > > > > > > > (gcc_jit_param_as_rvalue > > > > > > > > > (a), NULL), > > > > > > > > > > + GCC_JIT_BINARY_OP_PLUS, > > > > > > > > > > + gcc_jit_lvalue_as_rvalue ( > > > > > > > > > > + gcc_jit_rvalue_dereference > > > > > > > > > (gcc_jit_param_as_rvalue (c), NULL))); > > > > > > > > > > + /* *b +=3D *c; */ > > > > > > > > > > + gcc_jit_block_add_assignment_op ( > > > > > > > > > > + block, NULL, > > > > > > > > > > + gcc_jit_rvalue_dereference > > > > > > > > > > (gcc_jit_param_as_rvalue > > > > > > > > > (b), NULL), > > > > > > > > > > + GCC_JIT_BINARY_OP_PLUS, > > > > > > > > > > + gcc_jit_lvalue_as_rvalue ( > > > > > > > > > > + gcc_jit_rvalue_dereference > > > > > > > > > (gcc_jit_param_as_rvalue (c), NULL))); > > > > > > > > > > + > > > > > > > > > > + gcc_jit_block_end_with_void_return (block, NULL); > > > > > > > > > > +} > > > > > > > > > > + > > > > > > > > > > +/* { dg-final { jit-verify-output-file-was-created "" > > > > > > > > > > } } */ > > > > > > > > > > +/* { dg-final { jit-verify-assembler-output "addl > > > > > > > > > > %eax, > > > > > > > > > > (%rdi) > > > > > > > > > > + addl %eax, (%rsi)" } } */ > > > > > > > > > > -- > > > > > > > > > > 2.34.1 > > > > > > > > > > > > > > > > > > > > > > > > > > > > If this test is meant to run at -O3 and thus can't be > > > > > > > > > part of > > > > > > > > > test- > > > > > > > > > combination.c, please add a comment about it to > > > > > > > > > gcc/testsuite/jit.dg/all-non-failing-tests.h (in the > > > > > > > > > alphabetical > > > > > > > > > place). > > > > > > > > > > > > > > > > > > The patch also needs to add documentation for the new > > > > > > > > > entrypoint (in > > > > > > > > > topics/types.rst), and for the new ABI tag (in > > > > > > > > > topics/compatibility.rst). > > > > > > > > > > > > > > > > > > > > > > > > > > > Thanks again for the patch; hope the above is > > > > > > > > > constructive > > > > > > > > > Dave > > > > > > > > > > > > > > > > > > > >