In some applications (notably the Linux kernel), "break 0" is used as a trap that a handler may be able to recover. But in GCC the "trap" pattern is meant to make the program rightfully die instead.
As [1] describes, sometimes it's vital to distinguish between the two cases. Use the "documented illegal instruction" amswap.w $r0,$r1,$r0 for "trap" instead. This also aligns the behavior with x86_64 GCC and LoongArch clang. [1]:https://lore.kernel.org/[email protected] gcc/ * config/loongarch/loongarch.md (trap): Lower to the documented illegal amswap.w $r0,$r1,$r0. gcc/testsuite/ * gcc.target/loongarch/trap.c: New test. --- Bootstrapped and regtested on loongarch64-linux-gnu. Ok for trunk? gcc/config/loongarch/loongarch.md | 5 ++++- gcc/testsuite/gcc.target/loongarch/trap.c | 9 +++++++++ 2 files changed, 13 insertions(+), 1 deletion(-) create mode 100644 gcc/testsuite/gcc.target/loongarch/trap.c diff --git a/gcc/config/loongarch/loongarch.md b/gcc/config/loongarch/loongarch.md index a275a2d0158..f3873f5064c 100644 --- a/gcc/config/loongarch/loongarch.md +++ b/gcc/config/loongarch/loongarch.md @@ -679,11 +679,14 @@ (define_expand "<optab><mode>3" ;; .................... ;; +;; We used to use "break 0" but it's usually used as a trap that a signal +;; handler can caught. Using an insn that maps to an INE makes it more +;; likely the program will rightfully die. (define_insn "trap" [(trap_if (const_int 1) (const_int 0))] "" { - return "break\t0"; + return "amswap.w\t$r0,$r1,$r0"; } [(set_attr "type" "trap")]) diff --git a/gcc/testsuite/gcc.target/loongarch/trap.c b/gcc/testsuite/gcc.target/loongarch/trap.c new file mode 100644 index 00000000000..32948d4c822 --- /dev/null +++ b/gcc/testsuite/gcc.target/loongarch/trap.c @@ -0,0 +1,9 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -w -fisolate-erroneous-paths-dereference" } */ +/* { dg-final { scan-assembler "amswap\\.w\\t\\\$r0,\\\$r1,\\\$r0" } } */ + +int +bug (void) +{ + return *(int *)0; +} -- 2.51.0
