https://gcc.gnu.org/g:15c8169ec55b52630ab884dd7a30c3237ada98b2
commit r16-4701-g15c8169ec55b52630ab884dd7a30c3237ada98b2 Author: Xi Ruoyao <[email protected]> Date: Sun Oct 26 13:20:20 2025 +0800 LoongArch: Make the code generation of the trap pattern configurable 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. The kernel developers prefer "break 1" here, but in the user-space it's better to trigger a SIGILL instead of SIGTRAP as the latter is more likely used as a application-defined trap. To support both cases, make the code generation configurable with a new option. [1]:https://lore.kernel.org/[email protected] gcc/ * config/loongarch/genopts/loongarch.opt.in (-mbreak-code=): New. * config/loongarch/loongarch.opt: Regenerate. * config/loongarch/loongarch.md (trap): Separate to a define_insn and a define_expand which takes la_break_code. * doc/invoke.texi (-mbreak-code=): Document. * config/loongarch/loongarch.opt.urls: Regenerate. gcc/testsuite * gcc.target/loongarch/trap-default.c: New test. * gcc.target/loongarch/trap-1.c: New test. Diff: --- gcc/config/loongarch/genopts/loongarch.opt.in | 4 ++++ gcc/config/loongarch/loongarch.md | 14 +++++++++++--- gcc/config/loongarch/loongarch.opt | 4 ++++ gcc/config/loongarch/loongarch.opt.urls | 3 +++ gcc/doc/invoke.texi | 13 ++++++++++++- gcc/testsuite/gcc.target/loongarch/trap-1.c | 9 +++++++++ gcc/testsuite/gcc.target/loongarch/trap-default.c | 9 +++++++++ 7 files changed, 52 insertions(+), 4 deletions(-) diff --git a/gcc/config/loongarch/genopts/loongarch.opt.in b/gcc/config/loongarch/genopts/loongarch.opt.in index 39c1545e5408..f0c089a928ec 100644 --- a/gcc/config/loongarch/genopts/loongarch.opt.in +++ b/gcc/config/loongarch/genopts/loongarch.opt.in @@ -205,6 +205,10 @@ 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. + Enum Name(explicit_relocs) Type(int) The code model option names for -mexplicit-relocs: diff --git a/gcc/config/loongarch/loongarch.md b/gcc/config/loongarch/loongarch.md index be9a2351dd6e..625f30ca2658 100644 --- a/gcc/config/loongarch/loongarch.md +++ b/gcc/config/loongarch/loongarch.md @@ -679,14 +679,22 @@ ;; .................... ;; -(define_insn "trap" - [(trap_if (const_int 1) (const_int 0))] +(define_insn "*trap" + [(trap_if (const_int 1) (match_operand 0 "const_int_operand"))] "" { - return "break\t0"; + return (const_uimm15_operand (operands[0], VOIDmode) + ? "break\t%0" + : "amswap.w\t$r0,$r1,$r0"); } [(set_attr "type" "trap")]) +(define_expand "trap" + [(trap_if (const_int 1) (match_dup 0))] + "" +{ + operands[0] = GEN_INT (la_break_code); +}) ;; diff --git a/gcc/config/loongarch/loongarch.opt b/gcc/config/loongarch/loongarch.opt index fbe61c0bf7c2..628eabe8d591 100644 --- a/gcc/config/loongarch/loongarch.opt +++ b/gcc/config/loongarch/loongarch.opt @@ -213,6 +213,10 @@ 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. + Enum Name(explicit_relocs) Type(int) The code model option names for -mexplicit-relocs: diff --git a/gcc/config/loongarch/loongarch.opt.urls b/gcc/config/loongarch/loongarch.opt.urls index 606a211f3223..c93f04683e1c 100644 --- a/gcc/config/loongarch/loongarch.opt.urls +++ b/gcc/config/loongarch/loongarch.opt.urls @@ -48,6 +48,9 @@ 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) + mexplicit-relocs= UrlSuffix(gcc/LoongArch-Options.html#index-mexplicit-relocs-1) diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi index b40fc892fa0d..32b9c48f155c 100644 --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi @@ -1097,7 +1097,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 +-mno-check-zero-division -mbreak-code=@var{code} -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} @@ -28457,6 +28457,17 @@ 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 mcond-move-int @item -mcond-move-int @itemx -mno-cond-move-int diff --git a/gcc/testsuite/gcc.target/loongarch/trap-1.c b/gcc/testsuite/gcc.target/loongarch/trap-1.c new file mode 100644 index 000000000000..8936f60cce20 --- /dev/null +++ b/gcc/testsuite/gcc.target/loongarch/trap-1.c @@ -0,0 +1,9 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -w -fisolate-erroneous-paths-dereference -mbreak-code=1" } */ +/* { dg-final { scan-assembler "break\\t1" } } */ + +int +bug (void) +{ + return *(int *)0; +} diff --git a/gcc/testsuite/gcc.target/loongarch/trap-default.c b/gcc/testsuite/gcc.target/loongarch/trap-default.c new file mode 100644 index 000000000000..32948d4c8227 --- /dev/null +++ b/gcc/testsuite/gcc.target/loongarch/trap-default.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; +}
