public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
From: Tamar Christina <Tamar.Christina@arm.com>
To: Tamar Christina <Tamar.Christina@arm.com>,
	"gcc-patches@gcc.gnu.org"	<gcc-patches@gcc.gnu.org>
Cc: nd <nd@arm.com>, James Greenhalgh <James.Greenhalgh@arm.com>,
	Richard Earnshaw <Richard.Earnshaw@arm.com>,
	Marcus Shawcroft	<Marcus.Shawcroft@arm.com>
Subject: RE: [PATCH][GCC][AArch64] Make processing less fragile in config.gcc
Date: Tue, 25 Jun 2019 08:30:00 -0000	[thread overview]
Message-ID: <DB6PR0802MB230960F100DC15DF35081C99FFE30@DB6PR0802MB2309.eurprd08.prod.outlook.com> (raw)
In-Reply-To: <20190521170022.GA10685@arm.com>

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

Hi All,

This is an update to the patch rebased to after the SVE2 options have been merged.

Bootstrapped Regtested on aarch64-none-linux-gnu and no issues.

Ok for trunk?

Thanks,
Tamar

> -----Original Message-----
> From: gcc-patches-owner@gcc.gnu.org <gcc-patches-owner@gcc.gnu.org>
> On Behalf Of Tamar Christina
> Sent: Tuesday, May 21, 2019 18:00
> To: gcc-patches@gcc.gnu.org
> Cc: nd <nd@arm.com>; James Greenhalgh <James.Greenhalgh@arm.com>;
> Richard Earnshaw <Richard.Earnshaw@arm.com>; Marcus Shawcroft
> <Marcus.Shawcroft@arm.com>
> Subject: [PATCH][GCC][AArch64] Make processing less fragile in config.gcc
> 
> Hi All,
> 
> Due to config.gcc all the options need to be on one line because of the grep
> lines which would select only the first line of the option.
> 
> This causes it not to select the right bits on options that are spread over
> multiple lines when the --with-arch configure option is used.  The issue
> happens silently and you just get a compiler with an incorrect set of default
> flags.
> 
> The current rules are quite rigid:
> 
>    1) No space between the AARCH64_OPT_EXTENSION and the opening (.
>    2) No space between the opening ( and the extension name.
>    3) No space after the extension name before the ,.
>    4) Spaces are only allowed after a , and around |.
> 
> This patch makes this a lot less fragile by using the C pre-processor to flatten
> the list and then provides much more flexible regex using group matching to
> process the options instead of string replacement.  This removes all the
> restrictions above and makes the code a bit more readable.
> 
> Bootstrapped Regtested on aarch64-none-linux-gnu and no issues.
> 
> Ok for trunk? and for eventual backport?
> 
> Thanks,
> Tamar
> 
> gcc/ChangeLog:
> 
> 2019-05-21  Tamar Christina  <tamar.christina@arm.com>
> 
> 	PR target/89517
> 	* config.gcc: Relax parsing of AARCH64_OPT_EXTENSION.
> 	* config/aarch64/aarch64-option-extensions.def: Add new
> comments
> 	and restore easier to read options.
> 
> --

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: rb10757.patch --]
[-- Type: text/x-diff; name="rb10757.patch", Size: 13266 bytes --]

diff --git a/gcc/config.gcc b/gcc/config.gcc
index 7122c8ed1c89fdf4c79d9a2e27d8e81a882632c1..a6ae9fefe9c3086e2a2e9b310ef51098aa559691 100644
--- a/gcc/config.gcc
+++ b/gcc/config.gcc
@@ -3830,32 +3830,40 @@ case "${target}" in
 				  sed -e 's/,.*$//'`
 			  fi
 
+			  # Use the pre-processor to strip flatten the options.
+			  # This makes the format less rigid than if we use
+			  # grep and sed directly here.
+			  opt_macro="AARCH64_OPT_EXTENSION(A, B, C, D, E, F)=A, B, C, D, E, F"
+			  options_parsed="`$ac_cv_prog_CPP -D"$opt_macro" -x c \
+				${srcdir}/config/aarch64/aarch64-option-extensions.def`"
+
+			  # Match one element inside AARCH64_OPT_EXTENSION, we
+			  # consume anything that's not a ,.
+			  elem="[ 	]*\([^,]\+\)[ 	]*"
+
+			  # Repeat the pattern for the number of entries in the
+			  # AARCH64_OPT_EXTENSION, currently 6 times.
+			  sed_patt="^$elem,$elem,$elem,$elem,$elem,$elem"
+
 			  while [ x"$ext_val" != x ]
 			  do
 				ext_val=`echo $ext_val | sed -e 's/\+//'`
 				ext=`echo $ext_val | sed -e 's/\+.*//'`
 				base_ext=`echo $ext | sed -e 's/^no//'`
+				opt_line=`echo -e "$options_parsed" | \
+					grep "^\"$base_ext\""`
 
 				if [ x"$base_ext" = x ] \
-				    || grep "^AARCH64_OPT_EXTENSION(\"$base_ext\"," \
-				    ${srcdir}/config/aarch64/aarch64-option-extensions.def \
-				    > /dev/null; then
-
-				  ext_canon=`grep "^AARCH64_OPT_EXTENSION(\"$base_ext\"," \
-					${srcdir}/config/aarch64/aarch64-option-extensions.def | \
-					sed -e 's/^[^,]*,[ 	]*//' | \
-					sed -e 's/,.*$//'`
-				  ext_on=`grep "^AARCH64_OPT_EXTENSION(\"$base_ext\"," \
-					${srcdir}/config/aarch64/aarch64-option-extensions.def | \
-					sed -e 's/^[^,]*,[ 	]*[^,]*,[ 	]*//' | \
-					sed -e 's/,.*$//' | \
-					sed -e 's/).*$//'`
-				  ext_off=`grep "^AARCH64_OPT_EXTENSION(\"$base_ext\"," \
-					${srcdir}/config/aarch64/aarch64-option-extensions.def | \
-					sed -e 's/^[^,]*,[ 	]*[^,]*,[ 	]*[^,]*,[ 	]*//' | \
-					sed -e 's/,.*$//' | \
-					sed -e 's/).*$//'`
-
+				    || [[ -n $opt_line ]]; then
+
+				  # These regexp extract the elements based on
+				  # their group match index in the regexp.
+				  ext_canon=`echo -e "$opt_line" | \
+					sed -e "s/$sed_patt/\2/"`
+				  ext_on=`echo -e "$opt_line" | \
+					sed -e "s/$sed_patt/\3/"`
+				  ext_off=`echo -e "$opt_line" | \
+					sed -e "s/$sed_patt/\4/"`
 
 				  if [ $ext = $base_ext ]; then
 					# Adding extension
diff --git a/gcc/config/aarch64/aarch64-option-extensions.def b/gcc/config/aarch64/aarch64-option-extensions.def
index 4b10c62d20401a66374eb68e36531d73df300af1..f9f3d930d821ba20df2001ed9afda62a74d82299 100644
--- a/gcc/config/aarch64/aarch64-option-extensions.def
+++ b/gcc/config/aarch64/aarch64-option-extensions.def
@@ -45,32 +45,43 @@
      entries: aes, pmull, sha1, sha2 being present).  In that case this field
      should contain a space (" ") separated list of the strings in 'Features'
      that are required.  Their order is not important.  An empty string means
-     do not detect this feature during auto detection.  */
+     do not detect this feature during auto detection.
 
-/* NOTE: This file is being parsed by config.gcc and so the
-   AARCH64_OPT_EXTENSION must adhere to a strict format:
-   1) No space between the AARCH64_OPT_EXTENSION and the opening (.
-   2) No space between the opening ( and the extension name.
-   3) No space after the extension name before the ,.
-   4) Spaces are only allowed after a , and around |.
-   5) Everything must be on one line.  */
+     NOTE: Any changes to the AARCH64_OPT_EXTENSION macro need to be mirrored in
+     config.gcc.  */
 
 /* Enabling "fp" just enables "fp".
    Disabling "fp" also disables "simd", "crypto", "fp16", "aes", "sha2",
    "sha3", sm3/sm4, "sve", "sve2", "sve2-aes", "sve2-sha3", "sve2-sm4", and
    "bitperm".  */
-AARCH64_OPT_EXTENSION("fp", AARCH64_FL_FP, 0, AARCH64_FL_SIMD | AARCH64_FL_CRYPTO | AARCH64_FL_F16 | AARCH64_FL_AES | AARCH64_FL_SHA2 | AARCH64_FL_SHA3 | AARCH64_FL_SM4 | AARCH64_FL_SVE | AARCH64_FL_SVE2 | AARCH64_FL_SVE2_AES | AARCH64_FL_SVE2_SHA3 | AARCH64_FL_SVE2_SM4 | AARCH64_FL_SVE2_BITPERM, false, "fp")
+AARCH64_OPT_EXTENSION("fp", AARCH64_FL_FP, 0, AARCH64_FL_SIMD | \
+		      AARCH64_FL_CRYPTO | AARCH64_FL_F16 | AARCH64_FL_AES | \
+		      AARCH64_FL_SHA2 | AARCH64_FL_SHA3 | AARCH64_FL_SM4 | \
+		      AARCH64_FL_SVE | AARCH64_FL_SVE2 | AARCH64_FL_SVE2_AES | \
+		      AARCH64_FL_SVE2_SHA3 | AARCH64_FL_SVE2_SM4 | \
+		      AARCH64_FL_SVE2_BITPERM, false, "fp")
 
 /* Enabling "simd" also enables "fp".
    Disabling "simd" also disables "crypto", "dotprod", "aes", "sha2", "sha3",
    "sm3/sm4", "sve", "sve2", "sve2-aes", "sve2-sha3", "sve2-sm4", and "bitperm".
    */
-AARCH64_OPT_EXTENSION("simd", AARCH64_FL_SIMD, AARCH64_FL_FP, AARCH64_FL_CRYPTO | AARCH64_FL_DOTPROD | AARCH64_FL_AES | AARCH64_FL_SHA2 | AARCH64_FL_SHA3 | AARCH64_FL_SM4 | AARCH64_FL_SVE | AARCH64_FL_SVE2 | AARCH64_FL_SVE2_AES | AARCH64_FL_SVE2_SHA3 | AARCH64_FL_SVE2_SM4 | AARCH64_FL_SVE2_BITPERM, false, "asimd")
+AARCH64_OPT_EXTENSION("simd", AARCH64_FL_SIMD, AARCH64_FL_FP, \
+		      AARCH64_FL_CRYPTO | AARCH64_FL_DOTPROD | \
+		      AARCH64_FL_AES | AARCH64_FL_SHA2 | AARCH64_FL_SHA3 | \
+		      AARCH64_FL_SM4 | AARCH64_FL_SVE | AARCH64_FL_SVE2 | \
+		      AARCH64_FL_SVE2_AES | AARCH64_FL_SVE2_SHA3 | \
+		      AARCH64_FL_SVE2_SM4 | AARCH64_FL_SVE2_BITPERM, false, \
+		      "asimd")
 
 /* Enabling "crypto" also enables "fp", "simd", "aes" and "sha2".
    Disabling "crypto" disables "crypto", "aes", "sha2", "sha3" and "sm3/sm4",
    "sve2-aes", "sve2-sha3", "sve2-sm4".  */
-AARCH64_OPT_EXTENSION("crypto", AARCH64_FL_CRYPTO, AARCH64_FL_FP | AARCH64_FL_SIMD | AARCH64_FL_AES | AARCH64_FL_SHA2, AARCH64_FL_AES | AARCH64_FL_SHA2 | AARCH64_FL_SHA3 | AARCH64_FL_SM4 | AARCH64_FL_SVE2_AES | AARCH64_FL_SVE2_SHA3 | AARCH64_FL_SVE2_SM4, true, "aes pmull sha1 sha2")
+AARCH64_OPT_EXTENSION("crypto", AARCH64_FL_CRYPTO, AARCH64_FL_FP | \
+		      AARCH64_FL_SIMD | AARCH64_FL_AES | AARCH64_FL_SHA2, \
+		      AARCH64_FL_AES | AARCH64_FL_SHA2 | AARCH64_FL_SHA3 | \
+		      AARCH64_FL_SM4 | AARCH64_FL_SVE2_AES | \
+		      AARCH64_FL_SVE2_SHA3 | AARCH64_FL_SVE2_SM4, true, \
+		      "aes pmull sha1 sha2")
 
 /* Enabling or disabling "crc" only changes "crc".  */
 AARCH64_OPT_EXTENSION("crc", AARCH64_FL_CRC, 0, 0, false, "crc32")
@@ -81,43 +92,58 @@ AARCH64_OPT_EXTENSION("lse", AARCH64_FL_LSE, 0, 0, false, "atomics")
 /* Enabling "fp16" also enables "fp".
    Disabling "fp16" disables "fp16", "fp16fml", "sve", "sve2", "sve2-aes",
    "sve2-sha3", "sve2-sm4", and "bitperm".  */
-AARCH64_OPT_EXTENSION("fp16", AARCH64_FL_F16, AARCH64_FL_FP, AARCH64_FL_F16FML | AARCH64_FL_SVE | AARCH64_FL_SVE2 | AARCH64_FL_SVE2_AES | AARCH64_FL_SVE2_SHA3 | AARCH64_FL_SVE2_SM4 | AARCH64_FL_SVE2_BITPERM, false, "fphp asimdhp")
+AARCH64_OPT_EXTENSION("fp16", AARCH64_FL_F16, AARCH64_FL_FP, \
+		      AARCH64_FL_F16FML | AARCH64_FL_SVE | AARCH64_FL_SVE2 | \
+		      AARCH64_FL_SVE2_AES | AARCH64_FL_SVE2_SHA3 | \
+		      AARCH64_FL_SVE2_SM4 | AARCH64_FL_SVE2_BITPERM, false, \
+		      "fphp asimdhp")
 
 /* Enabling or disabling "rcpc" only changes "rcpc".  */
 AARCH64_OPT_EXTENSION("rcpc", AARCH64_FL_RCPC, 0, 0, false, "lrcpc")
 
 /* Enabling "rdma" also enables "fp", "simd".
    Disabling "rdma" just disables "rdma".  */
-AARCH64_OPT_EXTENSION("rdma", AARCH64_FL_RDMA, AARCH64_FL_FP | AARCH64_FL_SIMD, 0, false, "asimdrdm")
+AARCH64_OPT_EXTENSION("rdma", AARCH64_FL_RDMA, \
+		      AARCH64_FL_FP | AARCH64_FL_SIMD, 0, false, "asimdrdm")
 
 /* Enabling "dotprod" also enables "simd".
    Disabling "dotprod" only disables "dotprod".  */
-AARCH64_OPT_EXTENSION("dotprod", AARCH64_FL_DOTPROD, AARCH64_FL_SIMD, 0, false, "asimddp")
+AARCH64_OPT_EXTENSION("dotprod", AARCH64_FL_DOTPROD, AARCH64_FL_SIMD, 0, \
+		      false, "asimddp")
 
 /* Enabling "aes" also enables "simd".
    Disabling "aes" disables "aes" and "sve2-aes'.  */
-AARCH64_OPT_EXTENSION("aes", AARCH64_FL_AES, AARCH64_FL_SIMD, AARCH64_FL_SVE2_AES, false, "aes")
+AARCH64_OPT_EXTENSION("aes", AARCH64_FL_AES, AARCH64_FL_SIMD, \
+		      AARCH64_FL_SVE2_AES, false, "aes")
 
 /* Enabling "sha2" also enables "simd".
    Disabling "sha2" just disables "sha2".  */
-AARCH64_OPT_EXTENSION("sha2", AARCH64_FL_SHA2, AARCH64_FL_SIMD, 0, false, "sha1 sha2")
+AARCH64_OPT_EXTENSION("sha2", AARCH64_FL_SHA2, AARCH64_FL_SIMD, 0, false, \
+		      "sha1 sha2")
 
 /* Enabling "sha3" enables "simd" and "sha2".
    Disabling "sha3" disables "sha3" and "sve2-sha3".  */
-AARCH64_OPT_EXTENSION("sha3", AARCH64_FL_SHA3, AARCH64_FL_SIMD | AARCH64_FL_SHA2, AARCH64_FL_SVE2_SHA3, false, "sha3 sha512")
+AARCH64_OPT_EXTENSION("sha3", AARCH64_FL_SHA3, AARCH64_FL_SIMD | \
+		      AARCH64_FL_SHA2, AARCH64_FL_SVE2_SHA3, false, \
+		      "sha3 sha512")
 
 /* Enabling "sm4" also enables "simd".
    Disabling "sm4" disables "sm4" and "sve2-sm4".  */
-AARCH64_OPT_EXTENSION("sm4", AARCH64_FL_SM4, AARCH64_FL_SIMD, AARCH64_FL_SVE2_SM4, false, "sm3 sm4")
+AARCH64_OPT_EXTENSION("sm4", AARCH64_FL_SM4, AARCH64_FL_SIMD, \
+		      AARCH64_FL_SVE2_SM4, false, "sm3 sm4")
 
 /* Enabling "fp16fml" also enables "fp" and "fp16".
    Disabling "fp16fml" just disables "fp16fml".  */
-AARCH64_OPT_EXTENSION("fp16fml", AARCH64_FL_F16FML, AARCH64_FL_FP | AARCH64_FL_F16, 0, false, "asimdfml")
+AARCH64_OPT_EXTENSION("fp16fml", AARCH64_FL_F16FML, \
+		      AARCH64_FL_FP | AARCH64_FL_F16, 0, false, "asimdfml")
 
 /* Enabling "sve" also enables "fp16", "fp" and "simd".
    Disabling "sve" disables "sve", "sve2", "sve2-aes", "sve2-sha3", "sve2-sm4"
    and "bitperm".  */
-AARCH64_OPT_EXTENSION("sve", AARCH64_FL_SVE, AARCH64_FL_FP | AARCH64_FL_SIMD | AARCH64_FL_F16, AARCH64_FL_SVE2 | AARCH64_FL_SVE2_AES | AARCH64_FL_SVE2_SHA3 | AARCH64_FL_SVE2_SM4 | AARCH64_FL_SVE2_BITPERM, false, "sve")
+AARCH64_OPT_EXTENSION("sve", AARCH64_FL_SVE, AARCH64_FL_FP | AARCH64_FL_SIMD | \
+		      AARCH64_FL_F16, AARCH64_FL_SVE2 | AARCH64_FL_SVE2_AES | \
+		      AARCH64_FL_SVE2_SHA3 | AARCH64_FL_SVE2_SM4 | \
+		      AARCH64_FL_SVE2_BITPERM, false, "sve")
 
 /* Enabling/Disabling "profile" does not enable/disable any other feature.  */
 AARCH64_OPT_EXTENSION("profile", AARCH64_FL_PROFILE, 0, 0, false, "")
@@ -140,22 +166,33 @@ AARCH64_OPT_EXTENSION("predres", AARCH64_FL_PREDRES, 0, 0, false, "")
 /* Enabling "sve2" also enables "sve", "fp16", "fp", and "simd".
    Disabling "sve2" disables "sve2", "sve2-aes", "sve2-sha3", "sve2-sm4", and
    "bitperm".  */
-AARCH64_OPT_EXTENSION("sve2", AARCH64_FL_SVE2, AARCH64_FL_SVE | AARCH64_FL_FP | AARCH64_FL_SIMD | AARCH64_FL_F16, AARCH64_FL_SVE2_AES | AARCH64_FL_SVE2_SHA3 | AARCH64_FL_SVE2_SM4 | AARCH64_FL_SVE2_BITPERM, false, "")
+AARCH64_OPT_EXTENSION("sve2", AARCH64_FL_SVE2, AARCH64_FL_SVE | \
+		      AARCH64_FL_FP | AARCH64_FL_SIMD | AARCH64_FL_F16, \
+		      AARCH64_FL_SVE2_AES | AARCH64_FL_SVE2_SHA3 | \
+		      AARCH64_FL_SVE2_SM4 | AARCH64_FL_SVE2_BITPERM, false, "")
 
 /* Enabling "sve2-sm4" also enables "sm4", "simd", "fp16", "fp", "sve", and
    "sve2". Disabling "sve2-sm4" just disables "sve2-sm4".  */
-AARCH64_OPT_EXTENSION("sve2-sm4", AARCH64_FL_SVE2_SM4, AARCH64_FL_SM4 | AARCH64_FL_SIMD | AARCH64_FL_F16 | AARCH64_FL_FP | AARCH64_FL_SVE | AARCH64_FL_SVE2, 0, false, "")
+AARCH64_OPT_EXTENSION("sve2-sm4", AARCH64_FL_SVE2_SM4, AARCH64_FL_SM4 | \
+		      AARCH64_FL_SIMD | AARCH64_FL_F16 | AARCH64_FL_FP | \
+		      AARCH64_FL_SVE | AARCH64_FL_SVE2, 0, false, "")
 
 /* Enabling "sve2-aes" also enables "aes", "simd", "fp16", "fp", "sve", and
    "sve2". Disabling "sve2-aes" just disables "sve2-aes".  */
-AARCH64_OPT_EXTENSION("sve2-aes", AARCH64_FL_SVE2_AES, AARCH64_FL_AES | AARCH64_FL_SIMD | AARCH64_FL_F16 | AARCH64_FL_FP | AARCH64_FL_SVE | AARCH64_FL_SVE2, 0, false, "")
+AARCH64_OPT_EXTENSION("sve2-aes", AARCH64_FL_SVE2_AES, AARCH64_FL_AES | \
+		      AARCH64_FL_SIMD | AARCH64_FL_F16 | AARCH64_FL_FP | \
+		      AARCH64_FL_SVE | AARCH64_FL_SVE2, 0, false, "")
 
 /* Enabling "sve2-sha3" also enables "sha3", "simd", "fp16", "fp", "sve", and
    "sve2". Disabling "sve2-sha3" just disables "sve2-sha3".  */
-AARCH64_OPT_EXTENSION("sve2-sha3", AARCH64_FL_SVE2_SHA3, AARCH64_FL_SHA3 | AARCH64_FL_SIMD | AARCH64_FL_F16 | AARCH64_FL_FP | AARCH64_FL_SVE | AARCH64_FL_SVE2, 0, false, "")
+AARCH64_OPT_EXTENSION("sve2-sha3", AARCH64_FL_SVE2_SHA3, AARCH64_FL_SHA3 | \
+		      AARCH64_FL_SIMD | AARCH64_FL_F16 | AARCH64_FL_FP | \
+		      AARCH64_FL_SVE | AARCH64_FL_SVE2, 0, false, "")
 
 /* Enabling "bitperm" also enables "simd", "fp16", "fp", "sve", and "sve2".
    Disabling "bitperm" just disables "bitperm".  */
-AARCH64_OPT_EXTENSION("bitperm", AARCH64_FL_SVE2_BITPERM, AARCH64_FL_SIMD | AARCH64_FL_F16 | AARCH64_FL_FP | AARCH64_FL_SVE | AARCH64_FL_SVE2, 0, false, "")
+AARCH64_OPT_EXTENSION("bitperm", AARCH64_FL_SVE2_BITPERM, AARCH64_FL_SIMD | \
+		      AARCH64_FL_F16 | AARCH64_FL_FP | AARCH64_FL_SVE | \
+		      AARCH64_FL_SVE2, 0, false, "")
 
 #undef AARCH64_OPT_EXTENSION


  parent reply	other threads:[~2019-06-25  8:30 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-05-21 17:00 Tamar Christina
2019-05-24 16:23 ` Kyrill Tkachov
2019-06-25  8:30 ` Tamar Christina [this message]
2019-07-08 17:04   ` James Greenhalgh

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=DB6PR0802MB230960F100DC15DF35081C99FFE30@DB6PR0802MB2309.eurprd08.prod.outlook.com \
    --to=tamar.christina@arm.com \
    --cc=James.Greenhalgh@arm.com \
    --cc=Marcus.Shawcroft@arm.com \
    --cc=Richard.Earnshaw@arm.com \
    --cc=gcc-patches@gcc.gnu.org \
    --cc=nd@arm.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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).