RISC-V: Support multilib with extra options

Message ID 20260603081418.1898408-1-kito.cheng@sifive.com
State Committed
Delegated to: Kito Cheng
Headers
Series RISC-V: Support multilib with extra options |

Checks

Context Check Description
rivoscibot/toolchain-ci-rivos-lint warning Lint failed
rivoscibot/toolchain-ci-rivos-apply-patch success Patch applied
rivoscibot/toolchain-ci-rivos-build--newlib-rv64gcv-lp64d-multilib success Build passed
rivoscibot/toolchain-ci-rivos-build--linux-rv64gc_zba_zbb_zbc_zbs-lp64d-multilib success Build passed
rivoscibot/toolchain-ci-rivos-build--linux-rv64gcv-lp64d-multilib success Build passed
rivoscibot/toolchain-ci-rivos-test success Testing passed
linaro-tcwg-bot/tcwg_gcc_build--master-arm success Build passed
linaro-tcwg-bot/tcwg_gcc_check--master-arm success Test passed
linaro-tcwg-bot/tcwg_simplebootstrap_build--master-arm-bootstrap success Build passed
linaro-tcwg-bot/tcwg_simplebootstrap_build--master-aarch64-bootstrap success Build passed
linaro-tcwg-bot/tcwg_gcc_build--master-aarch64 fail Patch failed to apply

Commit Message

Kito Cheng June 3, 2026, 8:14 a.m. UTC
  The syntax of multilib-generator was defined as below:

```
<primary arch>-<abi>-<additional arches>-<extensions>
```

And now extend with one more optional argument:

```
<primary arch>-<abi>-<additional arches>-<extensions>[-<extra-options>]
```

Detail syntax of `<extra-option>`:
```
<extra-options> := <extra-option> ',' <extra-options>
                 | <extra-option>

<extra-option> := <option> '/' <multi-lib-folder>
```

NOTE: Dash ('-') in the option name must replace with underline ('_'),
      and leading dash should skip, e.g. `-fcf-protection=full` become
      `fcf_protection=full`.

e.g.

rv64imafdc_zicfiss_zicfilp-lp64d---fcf_protection=full/cfi

It will build a multilib with
`-march=rv64imafdc_zicfiss_zicfilp -mabi=lp64d -fcf-protection=full`

And will use `rv64imafdc_zicfiss_zicfilp/lp64d/cfi` as multilib folder.

gcc/ChangeLog:

	* config/riscv/multilib-generator: Support extra options in the
	multilib config string.
	* doc/install.texi (--with-multilib-generator): Document the extra
	options syntax.
---
 gcc/config/riscv/multilib-generator | 50 +++++++++++++++++++++--------
 gcc/doc/install.texi                | 35 ++++++++++++++++++--
 2 files changed, 70 insertions(+), 15 deletions(-)
  

Comments

Jeffrey Law June 3, 2026, 2:05 p.m. UTC | #1
On 6/3/2026 2:14 AM, Kito Cheng wrote:
> The syntax of multilib-generator was defined as below:
>
> ```
> <primary arch>-<abi>-<additional arches>-<extensions>
> ```
>
> And now extend with one more optional argument:
>
> ```
> <primary arch>-<abi>-<additional arches>-<extensions>[-<extra-options>]
> ```
>
> Detail syntax of `<extra-option>`:
> ```
> <extra-options> := <extra-option> ',' <extra-options>
>                   | <extra-option>
>
> <extra-option> := <option> '/' <multi-lib-folder>
> ```
>
> NOTE: Dash ('-') in the option name must replace with underline ('_'),
>        and leading dash should skip, e.g. `-fcf-protection=full` become
>        `fcf_protection=full`.
>
> e.g.
>
> rv64imafdc_zicfiss_zicfilp-lp64d---fcf_protection=full/cfi
>
> It will build a multilib with
> `-march=rv64imafdc_zicfiss_zicfilp -mabi=lp64d -fcf-protection=full`
>
> And will use `rv64imafdc_zicfiss_zicfilp/lp64d/cfi` as multilib folder.
>
> gcc/ChangeLog:
>
> 	* config/riscv/multilib-generator: Support extra options in the
> 	multilib config string.
> 	* doc/install.texi (--with-multilib-generator): Document the extra
> 	options syntax.
Given you know this code better than anyone, happy to step aside and let 
you self-approve :-)

jeff
  

Patch

diff --git a/gcc/config/riscv/multilib-generator b/gcc/config/riscv/multilib-generator
index 52419da7233..0bcf4508094 100755
--- a/gcc/config/riscv/multilib-generator
+++ b/gcc/config/riscv/multilib-generator
@@ -51,6 +51,7 @@  arches = collections.OrderedDict()
 abis = collections.OrderedDict()
 required = []
 reuse = []
+extra_multlib_option_dict = collections.OrderedDict()
 
 def arch_canonicalize(arch, isa_spec):
   this_file = os.path.abspath(os.path.join( __file__))
@@ -143,25 +144,45 @@  args = parser.parse_args()
 
 if args.cmodel:
   cmodels = [None] + args.cmodel.split(",")
+  for cmodel in cmodels[1:]:
+    extra_multlib_option_dict['mcmodel=%s' % cmodel] = cmodel
 else:
   cmodels = [None]
 
-cmodel_options = '/'.join(['mcmodel=%s' % x for x in cmodels[1:]])
-cmodel_dirnames = ' \\\n'.join(cmodels[1:])
-
 for cmodel in cmodels:
   for cfg in args.cfgs:
+    local_extra_multlib_option_dict = collections.OrderedDict()
     try:
-      (arch, abi, extra, ext) = cfg.split('-')
+      if cfg.count('-') == 3:
+        (arch, abi, extra, ext) = cfg.split('-')
+        extra_multlib_options = []
+      elif cfg.count('-') == 4:
+        (arch, abi, extra, ext, extra_multlib_option) = cfg.split('-')
+        # <extra-multilib-option> is a list of options separated by slash, and
+        # each option is consisted of option name and multi-lib dir separated by
+        # semicolon, the dash within the option should rewrite as underscore to
+        # prevent confusion of parsing.
+        # e.g.
+        # fcf_protection=full/cfi : -fcf-protection=full as option name and cfi
+        #                           as multilib path.
+        extra_multlib_options = extra_multlib_option.split(',')
+        for option in extra_multlib_options:
+          option = option.replace('_', '-')
+          option = option.split('/')
+          local_extra_multlib_option_dict[option[0]] = option[1]
+        extra_multlib_option_dict.update(local_extra_multlib_option_dict)
     except:
-      print ("Invalid configure string %s, <arch>-<abi>-<extra>-<extensions>\n"
+      print ("Invalid configure string %s, <arch>-<abi>-<extra>-<extensions>"
+             "[-<extra-multilib-option>]\n"
              "<extra> and <extensions> can be empty, "
              "e.g. rv32imafd-ilp32--" % cfg)
       sys.exit(1)
 
-    # Large code model only support rv64.
-    if cmodel == "large" and arch.startswith("rv32"):
+    # Compact and large code model only support rv64.
+    if cmodel in ["compact", "large"] and arch.startswith("rv32"):
       continue
+    elif cmodel:
+      local_extra_multlib_option_dict['mcmodel=%s' % cmodel] = cmodel
 
     arch = arch_canonicalize (arch, args.misa_spec)
     arches[arch] = 1
@@ -181,10 +202,13 @@  for cmodel in cmodels:
       arches[alt] = 1
       reuse.append('march.%s/mabi.%s=march.%s/mabi.%s' % (arch, abi, alt, abi))
 
-    if cmodel:
-      required.append('march=%s/mabi=%s/mcmodel=%s' % (arch, abi, cmodel))
-    else:
-      required.append('march=%s/mabi=%s' % (arch, abi))
+    extra_multlib_option_str = '/'.join(local_extra_multlib_option_dict.keys())
+
+    multilib_cfg_line = 'march=%s/mabi=%s' % (arch, abi)
+
+    if (len(extra_multlib_option_str) > 0):
+      multilib_cfg_line += '/' + extra_multlib_option_str
+    required.append(multilib_cfg_line)
 
   arch_options = '/'.join(['march=%s' % x for x in arches.keys()])
   arch_dirnames = ' \\\n'.join(arches.keys())
@@ -196,7 +220,7 @@  prog = sys.argv[0].split('/')[-1]
 print('# This file was generated by %s with the command:' % prog)
 print('#  %s' % ' '.join(sys.argv))
 
-print('MULTILIB_OPTIONS = %s %s %s' % (arch_options, abi_options, cmodel_options))
-print('MULTILIB_DIRNAMES = %s %s %s' % (arch_dirnames, abi_dirnames, cmodel_dirnames))
+print('MULTILIB_OPTIONS = %s %s %s' % (arch_options, abi_options, " ".join(extra_multlib_option_dict.keys())))
+print('MULTILIB_DIRNAMES = %s %s %s' % (arch_dirnames, abi_dirnames, " ".join(extra_multlib_option_dict.values())))
 print('MULTILIB_REQUIRED = %s' % ' \\\n'.join(required))
 print('MULTILIB_REUSE = %s' % ' \\\n'.join(reuse))
diff --git a/gcc/doc/install.texi b/gcc/doc/install.texi
index 84eafdb7f24..44f2f90d525 100644
--- a/gcc/doc/install.texi
+++ b/gcc/doc/install.texi
@@ -1558,8 +1558,9 @@  values, possibly consisting of a single value.  Currently only implemented
 for riscv*-*-elf*.  The accepted values and meanings are given below.
 
 
-Every config is constructed with four components: architecture string, ABI,
-reuse rule with architecture string and reuse rule with sub-extension.
+Every config is constructed with four mandatory components and one optional
+component: architecture string, ABI, reuse rule with architecture string,
+reuse rule with sub-extension and an optional list of extra options.
 
 Example 1: Add multi-lib support for rv32i with ilp32.
 @smallexample
@@ -1600,6 +1601,36 @@  medlow code model; rv64ima with lp64 and medany code model
 rv64ima-lp64--;--cmodel=medlow,medany
 @end smallexample
 
+A config may carry an optional fifth component, a list of extra options, which
+is appended after the sub-extension reuse rule:
+@smallexample
+<arch>-<abi>-<extra-arch>-<sub-ext>[-<extra-options>]
+@end smallexample
+
+The extra options are a comma separated list, and each entry pairs an option
+name with the multilib directory it should map to, separated by a slash:
+@smallexample
+<extra-options> := <extra-option> ',' <extra-options>
+                 | <extra-option>
+
+<extra-option>  := <option> '/' <multilib-folder>
+@end smallexample
+
+Because the dash (@samp{-}) is used as the component separator, any dash in an
+option name must be rewritten as an underscore (@samp{_}), and the leading dash
+of the option must be dropped.  For example, @option{-fcf-protection=full} is
+written as @code{fcf_protection=full}.
+
+Example 7: Add multi-lib support for rv64imafdc with lp64d, plus a variant
+built with @option{-fcf-protection=full} placed in the @file{cfi} directory.
+@smallexample
+rv64imafdc_zicfiss_zicfilp-lp64d---fcf_protection=full/cfi
+@end smallexample
+
+This builds a multilib with
+@option{-march=rv64imafdc_zicfiss_zicfilp -mabi=lp64d -fcf-protection=full}
+and uses @file{rv64imafdc_zicfiss_zicfilp/lp64d/cfi} as the multilib folder.
+
 @item --with-multi-buildlist=@var{file}
 Specify a file containing a list of multilib directories to build.