[RFC,3/5] ld: Add RISC-V --relax-zcmt option

Message ID 20260627104555.331493-4-jiawei@iscas.ac.cn
State New
Headers
Series RISC-V: Add Zcmt table-jump relaxation support |

Commit Message

Jiawei June 27, 2026, 10:45 a.m. UTC
  Expose Zcmt table-jump relaxation as an explicit opt-in RISC-V linker option,
and document the non-position-independent executable links and JVT CSR
requirement, and keep the optimization disabled by default.

ld/ChangeLog:

	* NEWS: Add --relax-zcmt entry.
	* emultempl/riscvelf.em: Handle --relax-zcmt option.
	* gen-doc.texi: Enable RISC-V docs.
	* ld.texi: Document --relax-zcmt.
	* ldlex.h (enum option_values): Add RELAX_ZCMT options.
---
 ld/NEWS                  |  3 +++
 ld/emultempl/riscvelf.em | 17 +++++++++++++++--
 ld/gen-doc.texi          |  2 +-
 ld/ld.texi               | 35 +++++++++++++++++++++++++++++++++++
 ld/ldlex.h               |  2 ++
 5 files changed, 56 insertions(+), 3 deletions(-)
  

Patch

diff --git a/ld/NEWS b/ld/NEWS
index 2de87ae227c..774eaf2c457 100644
--- a/ld/NEWS
+++ b/ld/NEWS
@@ -2,6 +2,9 @@ 
 
 Changes in 2.47:
 
+* Add the RISC-V --relax-zcmt option for opt-in Zcmt table-jump relaxation
+  in non-position-independent executable links.
+
 * Add a linker optimization level of zero.  Using "-O 0" on the linker command
   line will stop it from combining the contents of mergeable sections.  This
   can significantly speed up the link process at the cost of producing larger
diff --git a/ld/emultempl/riscvelf.em b/ld/emultempl/riscvelf.em
index 814109355d9..67c9c23f289 100644
--- a/ld/emultempl/riscvelf.em
+++ b/ld/emultempl/riscvelf.em
@@ -26,7 +26,8 @@  fragment <<EOF
 #include "elfxx-riscv.h"
 
 static struct riscv_elf_params params = { .relax_gp = 1,
-					  .check_uleb128 = 0};
+					  .check_uleb128 = 0,
+					  .relax_zcmt = 0};
 EOF
 
 # Define some shell vars to insert bits of code into the standard elf
@@ -36,6 +37,8 @@  PARSE_AND_LIST_LONGOPTS=${PARSE_AND_LIST_LONGOPTS}'
     { "no-relax-gp", no_argument, NULL, OPTION_NO_RELAX_GP },
     { "check-uleb128", no_argument, NULL, OPTION_CHECK_ULEB128 },
     { "no-check-uleb128", no_argument, NULL, OPTION_NO_CHECK_ULEB128 },
+    { "relax-zcmt", no_argument, NULL, OPTION_RELAX_ZCMT },
+    { "no-relax-zcmt", no_argument, NULL, OPTION_NO_RELAX_ZCMT },
 '
 
 PARSE_AND_LIST_OPTIONS=${PARSE_AND_LIST_OPTIONS}'
@@ -43,6 +46,8 @@  PARSE_AND_LIST_OPTIONS=${PARSE_AND_LIST_OPTIONS}'
   fprintf (file, _("  --no-relax-gp               Don'\''t perform GP relaxation\n"));
   fprintf (file, _("  --check-uleb128             Check if SUB_ULEB128 has non-zero addend\n"));
   fprintf (file, _("  --no-check-uleb128          Don'\''t check if SUB_ULEB128 has non-zero addend\n"));
+  fprintf (file, _("  --relax-zcmt                Enable RISC-V Zcmt table-jump relaxation\n"));
+  fprintf (file, _("  --no-relax-zcmt             Disable RISC-V Zcmt table-jump relaxation (default)\n"));
 '
 
 PARSE_AND_LIST_ARGS_CASES=${PARSE_AND_LIST_ARGS_CASES}'
@@ -61,6 +66,14 @@  PARSE_AND_LIST_ARGS_CASES=${PARSE_AND_LIST_ARGS_CASES}'
     case OPTION_NO_CHECK_ULEB128:
       params.check_uleb128 = 0;
       break;
+
+    case OPTION_RELAX_ZCMT:
+      params.relax_zcmt = 1;
+      break;
+
+    case OPTION_NO_RELAX_ZCMT:
+      params.relax_zcmt = 0;
+      break;
 '
 
 fragment <<EOF
@@ -81,7 +94,7 @@  riscv_elf_before_allocation (void)
 	ENABLE_RELAXATION;
     }
 
-  link_info.relax_pass = 2;
+  link_info.relax_pass = RELAX_PASS_END;
 }
 
 static void
diff --git a/ld/gen-doc.texi b/ld/gen-doc.texi
index 561869f485a..6f1902aa85c 100644
--- a/ld/gen-doc.texi
+++ b/ld/gen-doc.texi
@@ -21,6 +21,7 @@ 
 @set PDP11
 @set POWERPC
 @set POWERPC64
+@set RISCV
 @set Renesas
 @set S/390
 @set SPU
@@ -32,4 +33,3 @@ 
 @clear SingleFormat
 @set UsesEnvVars
 @c ------------------------------ end CONFIGURATION VARS
-
diff --git a/ld/ld.texi b/ld/ld.texi
index 9d6618a4307..ae6217bc70e 100644
--- a/ld/ld.texi
+++ b/ld/ld.texi
@@ -33,6 +33,7 @@ 
 @set PDP11
 @set POWERPC
 @set POWERPC64
+@set RISCV
 @set Renesas
 @set S/390
 @set SPU
@@ -4123,6 +4124,40 @@  in the PLT entries for MIPS R6.
 @c man end
 @end ifset
 
+@ifset RISCV
+@subsection Options specific to RISC-V targets
+
+@c man begin OPTIONS
+
+@table @gcctabopt
+
+@kindex --relax-zcmt
+@item --relax-zcmt
+Enable RISC-V Zcmt table-jump relaxation when the input architecture
+attributes permit the Zcmt extension.  The extension requires Zca and
+Zicsr, and is not compatible with Zcd.  This relaxation is disabled by
+default and is initially supported only for non-position-independent
+executable links.  It is conservatively disabled for PIC, PIE and shared
+links.
+
+When a non-empty @code{.riscv.jvt} section is emitted, the linker defines
+a local @code{__jvt_base$} symbol at the table base.  Programs using this
+relaxation must initialize the @code{jvt} CSR to @code{__jvt_base$}
+before executing @code{cm.jt} or @code{cm.jalt}.  The symbol is not
+defined when no profitable table is emitted; generic startup code that
+unconditionally references @code{__jvt_base$} is therefore unsupported
+unless it arranges an optional reference or is linked only when a JVT is
+emitted.
+
+@kindex --no-relax-zcmt
+@item --no-relax-zcmt
+Disable RISC-V Zcmt table-jump relaxation.  This is the default.
+
+@end table
+
+@c man end
+@end ifset
+
 
 @ifset PDP11
 @subsection Options specific to PDP11 targets
diff --git a/ld/ldlex.h b/ld/ldlex.h
index 958ec3fbf81..03057e27852 100644
--- a/ld/ldlex.h
+++ b/ld/ldlex.h
@@ -431,6 +431,8 @@  enum option_values
   OPTION_NO_RELAX_GP,
   OPTION_CHECK_ULEB128,
   OPTION_NO_CHECK_ULEB128,
+  OPTION_RELAX_ZCMT,
+  OPTION_NO_RELAX_ZCMT,
   /* Used by emultempl/rxelf.em.  */
   OPTION_NO_FLAG_MISMATCH_WARNINGS,
   OPTION_IGNORE_LMA,