From: WANG Xuerui <[email protected]>

The option was introduced a few days ago to provide more control over
the code generation of __builtin_trap(), but the current form does not
provide room for further extension should other means of trapping become
available on future generations of LoongArch cores.  Moreover, using
out-of-range values to ask for something that's not a "break" is
counter-intuitive, at least for an option named "break"-something.

To improve the command-line UX, rename the option to
-mbuiltin-trap-impl= to better reflect the intent from a user's
perspective, and make it accept a string that resembles real LoongArch
assembly if the user were asked to write the trap snippet themselves.

For now, the accepted forms are "break-CODE" where CODE is an integer
literal between 0 and 32767 inclusive, and "amswap.w".  Both deviate
from usual assembly forms somehow for practical reasons:

1. Spaces are notorious in CLI argument handling, so for something
   expected to be passed around often in an unstructured way (read:
   CFLAGS), it is prudent to use something else.
2. The usage of "amswap.w" here (or any other AM* instruction) is
   exotic, as the LoongArch reference manual does not provide any other
   way to trigger an INE (instruction non-existent) exception for sure.
   In this case, the register operands are intentionally illegal, so
   having them fully spelled out only serves to confuse any reader. In
   addition, the exact register usage is irrelevant to the option's
   purpose.

Since this is now freeform string, any future evolution of the option's
usage is made possible.

gcc/ChangeLog:

        * config/loongarch/genopts/loongarch.opt.in: Rework
          -mbreak-code= into -mbuiltin-trap-impl=.
        * config/loongarch/loongarch-opts.cc
        (loongarch_parse_mbuiltin_trap_impl): New function.
        (loongarch_init_misc_options): Parse the new option.
        * config/loongarch/loongarch.opt: Regenerate.
        * config/loongarch/loongarch.opt.urls: Regenerate.
        * doc/invoke.texi: Amend documentation.

gcc/testsuite/ChangeLog:

        * gcc.target/loongarch/trap-1.c: Move to...
        * gcc.target/loongarch/builtin-trap-impl-break-1.c: ...here and
          migrate to new option.
        * gcc.target/loongarch/trap-default.c: Move to...
        * gcc.target/loongarch/builtin-trap-impl-default.c: ...here and
          migrate to new option.
        * gcc.target/loongarch/builtin-trap-impl-amswap-w.c: New test.
        * gcc.target/loongarch/builtin-trap-impl-break-0.c: New test.
        * gcc.target/loongarch/builtin-trap-impl-break-32767.c: New test.
        * gcc.target/loongarch/builtin-trap-impl-err-1.c: New test.
        * gcc.target/loongarch/builtin-trap-impl-err-2.c: New test.
        * gcc.target/loongarch/builtin-trap-impl-test.c: New common test
          code.

Signed-off-by: WANG Xuerui <[email protected]>
---

Bootstrapped and regtested on loongarch64-linux-gnu.  Ok for trunk?

Changes in v2:

- regenerated loongarch.opt.urls (suggested by Ruoyao)
- added Signed-off-by tag

 gcc/config/loongarch/genopts/loongarch.opt.in | 11 ++++--
 gcc/config/loongarch/loongarch-opts.cc        | 38 ++++++++++++++++++
 gcc/config/loongarch/loongarch.opt            | 11 ++++--
 gcc/config/loongarch/loongarch.opt.urls       |  4 +-
 gcc/doc/invoke.texi                           | 39 +++++++++++++------
 .../loongarch/builtin-trap-impl-amswap-w.c    |  6 +++
 .../loongarch/builtin-trap-impl-break-0.c     |  6 +++
 .../{trap-1.c => builtin-trap-impl-break-1.c} |  9 ++---
 .../loongarch/builtin-trap-impl-break-32767.c |  6 +++
 ...-default.c => builtin-trap-impl-default.c} |  7 +---
 .../loongarch/builtin-trap-impl-err-1.c       |  7 ++++
 .../loongarch/builtin-trap-impl-err-2.c       |  7 ++++
 .../loongarch/builtin-trap-impl-test.c        |  9 +++++
 13 files changed, 129 insertions(+), 31 deletions(-)
 create mode 100644 
gcc/testsuite/gcc.target/loongarch/builtin-trap-impl-amswap-w.c
 create mode 100644 
gcc/testsuite/gcc.target/loongarch/builtin-trap-impl-break-0.c
 rename gcc/testsuite/gcc.target/loongarch/{trap-1.c => 
builtin-trap-impl-break-1.c} (58%)
 create mode 100644 
gcc/testsuite/gcc.target/loongarch/builtin-trap-impl-break-32767.c
 rename gcc/testsuite/gcc.target/loongarch/{trap-default.c => 
builtin-trap-impl-default.c} (71%)
 create mode 100644 gcc/testsuite/gcc.target/loongarch/builtin-trap-impl-err-1.c
 create mode 100644 gcc/testsuite/gcc.target/loongarch/builtin-trap-impl-err-2.c
 create mode 100644 gcc/testsuite/gcc.target/loongarch/builtin-trap-impl-test.c

diff --git a/gcc/config/loongarch/genopts/loongarch.opt.in 
b/gcc/config/loongarch/genopts/loongarch.opt.in
index f0c089a928e..82f6106992a 100644
--- a/gcc/config/loongarch/genopts/loongarch.opt.in
+++ b/gcc/config/loongarch/genopts/loongarch.opt.in
@@ -205,9 +205,14 @@ mmax-inline-memcpy-size=
 Target Joined RejectNegative UInteger Var(la_max_inline_memcpy_size) 
Init(1024) Save
 -mmax-inline-memcpy-size=SIZE  Set the max size of memcpy to inline, default 
is 1024.
 
-mbreak-code=
-Target Joined UInteger Var(la_break_code) Init(-1) Save
--mbreak-code=CODE      Use 'break CODE' for traps supposed to be 
unrecoverable, or an 'amswap.w' instruction leading to INE if CODE is out of 
range.
+TargetVariable
+int la_break_code = -1
+
+mbuiltin-trap-impl=
+Target Joined RejectNegative Var(la_builtin_trap_impl) Init("") Save
+Control how __builtin_trap is code-generated and its runtime behavior.
+Possible values are \"break-CODE\" (0 <= CODE <= 32767) for a BRK with the
+given CODE, or \"amswap.w\" for a documented INE.
 
 Enum
 Name(explicit_relocs) Type(int)
diff --git a/gcc/config/loongarch/loongarch-opts.cc 
b/gcc/config/loongarch/loongarch-opts.cc
index cacfe370345..3668788b07e 100644
--- a/gcc/config/loongarch/loongarch-opts.cc
+++ b/gcc/config/loongarch/loongarch-opts.cc
@@ -1045,6 +1045,40 @@ loongarch_target_option_override (struct 
loongarch_target *target,
 }
 
 
+/* Parser for -mbuiltin-trap-impl=STRATEGY.  */
+int
+loongarch_parse_mbuiltin_trap_impl (const char *val)
+{
+  if (!val || *val == '\0' || !strcmp (val, "amswap.w"))
+    return -1;
+
+  if (!strncmp (val, "break-", 6))
+    {
+      const char *code_substr = val + 6;
+      int err = 0;
+      HOST_WIDE_INT r = integral_argument (code_substr, &err, false);
+      if (err || r < 0 || r > 0x7fff)
+       {
+         error ("code %qs invalid for the %qs instruction", code_substr,
+                "break");
+         inform (UNKNOWN_LOCATION,
+                 "code for the %qs instruction must be an integer between "
+                 "%d and %d, inclusive",
+                 "break", 0, 0x7fff);
+         return -1;
+       }
+      return (int) r;
+    }
+
+  error ("unrecognized strategy for %<-mbuiltin-trap-impl%>: %qs", val);
+  inform (UNKNOWN_LOCATION,
+         "valid values are %<break-CODE%> (CODE between %d and %d, "
+         "inclusive) and %<amswap.w%>",
+         0, 0x7fff);
+  return -1;
+}
+
+
 /* Resolve options that's not covered by la_target.  */
 void
 loongarch_init_misc_options (struct gcc_options *opts,
@@ -1056,6 +1090,10 @@ loongarch_init_misc_options (struct gcc_options *opts,
   /* -mrecip options.  */
   opts->x_recip_mask = loongarch_parse_mrecip_scheme (opts->x_la_recip_name);
 
+  /* -mbuiltin-trap-impl.  */
+  opts->x_la_break_code
+      = loongarch_parse_mbuiltin_trap_impl (opts->x_la_builtin_trap_impl);
+
 #define INIT_TARGET_FLAG(NAME, INIT) \
   { \
     if (!(opts_set->x_target_flags & MASK_##NAME)) \
diff --git a/gcc/config/loongarch/loongarch.opt 
b/gcc/config/loongarch/loongarch.opt
index 628eabe8d59..12d9c538dc5 100644
--- a/gcc/config/loongarch/loongarch.opt
+++ b/gcc/config/loongarch/loongarch.opt
@@ -213,9 +213,14 @@ mmax-inline-memcpy-size=
 Target Joined RejectNegative UInteger Var(la_max_inline_memcpy_size) 
Init(1024) Save
 -mmax-inline-memcpy-size=SIZE  Set the max size of memcpy to inline, default 
is 1024.
 
-mbreak-code=
-Target Joined UInteger Var(la_break_code) Init(-1) Save
--mbreak-code=CODE      Use 'break CODE' for traps supposed to be 
unrecoverable, or an 'amswap.w' instruction leading to INE if CODE is out of 
range.
+TargetVariable
+int la_break_code = -1
+
+mbuiltin-trap-impl=
+Target Joined RejectNegative Var(la_builtin_trap_impl) Init("") Save
+Control how __builtin_trap is code-generated and its runtime behavior.
+Possible values are \"break-CODE\" (0 <= CODE <= 32767) for a BRK with the
+given CODE, or \"amswap.w\" for a documented INE.
 
 Enum
 Name(explicit_relocs) Type(int)
diff --git a/gcc/config/loongarch/loongarch.opt.urls 
b/gcc/config/loongarch/loongarch.opt.urls
index c93f04683e1..202040bbe26 100644
--- a/gcc/config/loongarch/loongarch.opt.urls
+++ b/gcc/config/loongarch/loongarch.opt.urls
@@ -48,8 +48,8 @@ UrlSuffix(gcc/LoongArch-Options.html#index-mstrict-align-1)
 mmax-inline-memcpy-size=
 UrlSuffix(gcc/LoongArch-Options.html#index-mmax-inline-memcpy-size)
 
-mbreak-code=
-UrlSuffix(gcc/LoongArch-Options.html#index-mbreak-code)
+mbuiltin-trap-impl=
+UrlSuffix(gcc/LoongArch-Options.html#index-mbuiltin-trap-impl)
 
 mexplicit-relocs=
 UrlSuffix(gcc/LoongArch-Options.html#index-mexplicit-relocs-1)
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index df4331fbad0..060f70c4d91 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -1155,7 +1155,7 @@ Objective-C and Objective-C++ Dialects}.
 -mfpu=@var{fpu-type} -msimd=@var{simd-type}
 -msoft-float -msingle-float -mdouble-float -mlsx -mno-lsx -mlasx -mno-lasx
 -mbranch-cost=@var{n} -maddr-reg-reg-cost=@var{n}  -mcheck-zero-division
--mno-check-zero-division -mbreak-code=@var{code}
+-mno-check-zero-division -mbuiltin-trap-impl=@var{strategy}
 -mcond-move-int  -mno-cond-move-int
 -mcond-move-float  -mno-cond-move-float
 -memcpy  -mno-memcpy -mstrict-align -mno-strict-align -G @var{num}
@@ -16333,7 +16333,7 @@ as a parameter of @code{free} call or compared with 
@code{NULL}.  If
 with @option{-fmalloc-dce=2} also comparisons with @code{NULL} pointer are
 considered safe to remove.
 
-The default is @option{-fmalloc-dce=2}.  See also @option{-fallocation-dce}. 
+The default is @option{-fmalloc-dce=2}.  See also @option{-fallocation-dce}.
 
 @opindex fmove-loop-invariants
 @item -fmove-loop-invariants
@@ -28757,16 +28757,31 @@ Trap (do not trap) on integer division by zero.  The 
default is
 @option{-mcheck-zero-division} for @option{-O0} or @option{-Og}, and
 @option{-mno-check-zero-division} for other optimization levels.
 
-@opindex mbreak-code
-@item -mbreak-code=@var{code}
-Emit a @code{break} @var{code} instruction for irrecoverable traps
-from @code{__builtin_trap} or inserted by the compiler (for example
-an erroneous path isolated with
-@option{-fisolate-erroneous-paths-dereference}), or an
-@code{amswap.w $r0, $r1, $r0} instruction which will cause the hardware
-to trigger an Instruction Not-defined Exception if @var{code} is negative
-or greater than 32767.  The default is -1, meaning to use the
-@code{amswap.w} instruction.
+@opindex mbuiltin-trap-impl
+@item -mbuiltin-trap-impl=@var{strategy}
+Control the code generated for irrecoverable traps from
+@code{__builtin_trap} or inserted by the compiler (for example an
+erroneous path isolated with
+@option{-fisolate-erroneous-paths-dereference}).
+
+The following forms are supported for @var{strategy}:
+
+@itemize @bullet
+@item
+@code{amswap.w}
+Use @code{amswap.w $r0, $r1, $r0} for traps, which is a documented
+illegal use of the instruction.  An @code{INE} (Instruction
+non-existent) exception will be triggered at runtime.
+
+@item
+@code{break-CODE}
+Use @code{break} @var{CODE} for traps.  @var{CODE} must be an integer
+literal between 0 and 32767 inclusive, due to the @code{break}
+instruction's encoding.  A @code{BRK} (Breakpoint) exception will be
+triggered at runtime.
+@end itemize
+
+The default is to use the @code{amswap.w} strategy.
 
 @opindex mcond-move-int
 @item -mcond-move-int
diff --git a/gcc/testsuite/gcc.target/loongarch/builtin-trap-impl-amswap-w.c 
b/gcc/testsuite/gcc.target/loongarch/builtin-trap-impl-amswap-w.c
new file mode 100644
index 00000000000..2b4d48088ba
--- /dev/null
+++ b/gcc/testsuite/gcc.target/loongarch/builtin-trap-impl-amswap-w.c
@@ -0,0 +1,6 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -w -fisolate-erroneous-paths-dereference 
-mbuiltin-trap-impl=amswap.w" } */
+/* { dg-final { scan-assembler "amswap\\.w\\t\\\$r0,\\\$r1,\\\$r0" } } */
+
+#define BUILTIN_TRAP_IMPL_TEST
+#include "builtin-trap-impl-test.c"
diff --git a/gcc/testsuite/gcc.target/loongarch/builtin-trap-impl-break-0.c 
b/gcc/testsuite/gcc.target/loongarch/builtin-trap-impl-break-0.c
new file mode 100644
index 00000000000..a20960f0a1c
--- /dev/null
+++ b/gcc/testsuite/gcc.target/loongarch/builtin-trap-impl-break-0.c
@@ -0,0 +1,6 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -w -fisolate-erroneous-paths-dereference 
-mbuiltin-trap-impl=break-0" } */
+/* { dg-final { scan-assembler "break\\t0" } } */
+
+#define BUILTIN_TRAP_IMPL_TEST
+#include "builtin-trap-impl-test.c"
diff --git a/gcc/testsuite/gcc.target/loongarch/trap-1.c 
b/gcc/testsuite/gcc.target/loongarch/builtin-trap-impl-break-1.c
similarity index 58%
rename from gcc/testsuite/gcc.target/loongarch/trap-1.c
rename to gcc/testsuite/gcc.target/loongarch/builtin-trap-impl-break-1.c
index 8936f60cce2..fe6a63c777a 100644
--- a/gcc/testsuite/gcc.target/loongarch/trap-1.c
+++ b/gcc/testsuite/gcc.target/loongarch/builtin-trap-impl-break-1.c
@@ -1,9 +1,6 @@
 /* { dg-do compile } */
-/* { dg-options "-O2 -w -fisolate-erroneous-paths-dereference -mbreak-code=1" 
} */
+/* { dg-options "-O2 -w -fisolate-erroneous-paths-dereference 
-mbuiltin-trap-impl=break-1" } */
 /* { dg-final { scan-assembler "break\\t1" } } */
 
-int
-bug (void)
-{
-  return *(int *)0;
-}
+#define BUILTIN_TRAP_IMPL_TEST
+#include "builtin-trap-impl-test.c"
diff --git a/gcc/testsuite/gcc.target/loongarch/builtin-trap-impl-break-32767.c 
b/gcc/testsuite/gcc.target/loongarch/builtin-trap-impl-break-32767.c
new file mode 100644
index 00000000000..3ae5b0a68f7
--- /dev/null
+++ b/gcc/testsuite/gcc.target/loongarch/builtin-trap-impl-break-32767.c
@@ -0,0 +1,6 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -w -fisolate-erroneous-paths-dereference 
-mbuiltin-trap-impl=break-0x7fff" } */
+/* { dg-final { scan-assembler "break\\t32767" } } */
+
+#define BUILTIN_TRAP_IMPL_TEST
+#include "builtin-trap-impl-test.c"
diff --git a/gcc/testsuite/gcc.target/loongarch/trap-default.c 
b/gcc/testsuite/gcc.target/loongarch/builtin-trap-impl-default.c
similarity index 71%
rename from gcc/testsuite/gcc.target/loongarch/trap-default.c
rename to gcc/testsuite/gcc.target/loongarch/builtin-trap-impl-default.c
index 32948d4c822..50a17cfc1d5 100644
--- a/gcc/testsuite/gcc.target/loongarch/trap-default.c
+++ b/gcc/testsuite/gcc.target/loongarch/builtin-trap-impl-default.c
@@ -2,8 +2,5 @@
 /* { dg-options "-O2 -w -fisolate-erroneous-paths-dereference" } */
 /* { dg-final { scan-assembler "amswap\\.w\\t\\\$r0,\\\$r1,\\\$r0" } } */
 
-int
-bug (void)
-{
-  return *(int *)0;
-}
+#define BUILTIN_TRAP_IMPL_TEST
+#include "builtin-trap-impl-test.c"
diff --git a/gcc/testsuite/gcc.target/loongarch/builtin-trap-impl-err-1.c 
b/gcc/testsuite/gcc.target/loongarch/builtin-trap-impl-err-1.c
new file mode 100644
index 00000000000..857e5951158
--- /dev/null
+++ b/gcc/testsuite/gcc.target/loongarch/builtin-trap-impl-err-1.c
@@ -0,0 +1,7 @@
+/* { dg-do compile } */
+/* { dg-options "-mbuiltin-trap-impl=break" } */
+
+int dummy;
+
+/* { dg-error "unrecognized strategy for '-mbuiltin-trap-impl': 'break'" "" { 
target { "loongarch*-*-*" } } 0 } */
+/* { dg-message "note: valid values are 'break-CODE' \\(CODE between 0 and 
32767, inclusive\\) and 'amswap.w'" "" { target { "loongarch*-*-*" } } 0 } */
diff --git a/gcc/testsuite/gcc.target/loongarch/builtin-trap-impl-err-2.c 
b/gcc/testsuite/gcc.target/loongarch/builtin-trap-impl-err-2.c
new file mode 100644
index 00000000000..e6ffd00a535
--- /dev/null
+++ b/gcc/testsuite/gcc.target/loongarch/builtin-trap-impl-err-2.c
@@ -0,0 +1,7 @@
+/* { dg-do compile } */
+/* { dg-options "-mbuiltin-trap-impl=break-32768" } */
+
+int dummy;
+
+/* { dg-error "code '32768' invalid for the 'break' instruction" "" { target { 
"loongarch*-*-*" } } 0 } */
+/* { dg-message "note: code for the 'break' instruction must be an integer 
between 0 and 32767, inclusive" "" { target { "loongarch*-*-*" } } 0 } */
diff --git a/gcc/testsuite/gcc.target/loongarch/builtin-trap-impl-test.c 
b/gcc/testsuite/gcc.target/loongarch/builtin-trap-impl-test.c
new file mode 100644
index 00000000000..a3daf81b478
--- /dev/null
+++ b/gcc/testsuite/gcc.target/loongarch/builtin-trap-impl-test.c
@@ -0,0 +1,9 @@
+#ifdef BUILTIN_TRAP_IMPL_TEST
+int
+bug (void)
+{
+  return *(int *)0;
+}
+#endif
+
+int dummy;
-- 
2.51.2

Reply via email to